内存池中如何保存内存块大小信息

2024-01-03 08:32

本文主要是介绍内存池中如何保存内存块大小信息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

网络设备因为需要快速的处理数据包,所以与Linux内核不同,网络设备中数据包和session的内存一般都是预先分配的。由于业务的不同,需要内存的大小可能只是固定的几个值。因此也就有几个固定内存大小的内存池。

使用内存池的好处:
1. 可以避免频繁分配和释放内存,提高效率;
2. 可以避免内存碎片;

下面讨论一下内存池的实现:为了 保证接口与malloc/free的一致性,对上层应用透明:
那么以malloc调用为例,ptr = malloc(size),调用者传入一个size。内存模块需要根据size的大小选择合适的内存池来分配内存。释放内存的时候,调用为free(ptr)。这时需要将内存重新放入对应的内存池。但是释放的时候,调用者并不将size大小传给内存模块,这就需要内存模块自己保存该内存的大小。

1)最直接的方法:在分配的内存块加上head或者tail块。
内存在内存池的组织如下:
首部用于保存内存块的大小以及保护信息,控制信息等。尾部可有可无,一般用于作为两块内存之间的保护区域。将其填充为一些特殊的值,用于检测内存错误,如越界溢出等。返回给应用的地址为黄色区域的起始地址。在释放的时候,由于首部的大小是固定的,可以从参数指针得到首部地址,从而得到内存模块所需要的一切信息。

这样的实现比较简单,但是却有缺点:应用申请内存时,传入的内存大小可能是应用精心设计好的。比如应用为了提高cache的命中率,申请内存时特意将size与cache line对齐。但是这种内存池的实现,却破坏了应用的初衷。

如何解决这个问题呢?可以把首部对齐至cache line。但是这样无疑是对内存的极大的浪费!比如cache line为64 bytes,首部就要占到64 bytes。这样的解决方法无疑是不可以接受的。

2)利用内存地址判断

这是一个简单的示意图。所有同大小的内存都是位于连续的内存中,构成一个大块内存。然后后面跟随另外大小的内存块,依次类推。当然不同大小的内存块可以不连续。

这样的实现,在释放内存的时候,可以通过传入的内存地址确定其所属的内存池。因为该大小的内存池的起始和终止地址是确定的。

再说一下这种实现的缺点:通用的内存池实现应该支持内存块的分裂和合并。当对应大小的内存使用完后,将更大的内存块分裂,一个用于返回,另一个插入到合适的内存池中。释放内存时,需要在适当的时机,将连续的小内存块合并为大块内存,并移到大内存池中。

上面的实现无疑不支持这种机制。即使强制支持,代价也很大。

3)内存块中保存size信息
即直接占用应用申请的内存块的部分地址,用于保存size信息。为了节约内存,不需要保存内存的大小,可以使用两三个bit来表示size类型。在释放内存的时候,根据size类型,找到正确的内存池。

这样的设计,实现也比较简单,且比较容易支持内存块的分裂和合并。但是由于size类型直接占用了应用内存的空间。对于调用者来说,必须要明确这一size类型的存在。这对调用者增加了额外的要求。一旦调用者没有注意到这个size类型。在拿到内存指针后,对整个内存进行了初始化。那么在释放内存的时候,要么导致内存泄露,要么会造成内存的越界。前者是将内存错误的放入了小的内存池中,后者是将内存错误的放入了大的内存中。
4) 由调用者保存内存大小
这种实现也很简单。内存模块并不维护内存块的大小。那么调用者需要在释放内存的时候,告诉内存模块,该块内存的大小。如申请时ptr = malloc(size);释放时free(ptr, size);缺点就是与C库的内存接口不匹配。


转自:http://blog.chinaunix.net/uid-23629988-id-3264806.html

这篇关于内存池中如何保存内存块大小信息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/565092

相关文章

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

SQL Server 查询数据库及数据文件大小的方法

《SQLServer查询数据库及数据文件大小的方法》文章介绍了查询数据库大小的SQL方法及存储过程实现,涵盖当前数据库、所有数据库的总大小及文件明细,本文结合实例代码给大家介绍的非常详细,感兴趣的... 目录1. 直接使用SQL1.1 查询当前数据库大小1.2 查询所有数据库的大小1.3 查询每个数据库的详

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

java内存泄漏排查过程及解决

《java内存泄漏排查过程及解决》公司某服务内存持续增长,疑似内存泄漏,未触发OOM,排查方法包括检查JVM配置、分析GC执行状态、导出堆内存快照并用IDEAProfiler工具定位大对象及代码... 目录内存泄漏内存问题排查1.查看JVM内存配置2.分析gc是否正常执行3.导出 dump 各种工具分析4.

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu