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

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

相关文章

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Linux查看系统盘和SSD盘的容量、型号及挂载信息的方法

《Linux查看系统盘和SSD盘的容量、型号及挂载信息的方法》在Linux系统中,管理磁盘设备和分区是日常运维工作的重要部分,而lsblk命令是一个强大的工具,它用于列出系统中的块设备(blockde... 目录1. 查看所有磁盘的物理信息方法 1:使用 lsblk(推荐)方法 2:使用 fdisk -l(

SpringBoot如何对密码等敏感信息进行脱敏处理

《SpringBoot如何对密码等敏感信息进行脱敏处理》这篇文章主要为大家详细介绍了SpringBoot对密码等敏感信息进行脱敏处理的几个常用方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录​1. 配置文件敏感信息脱敏​​2. 日志脱敏​​3. API响应脱敏​​4. 其他注意事项​​总结

Java内存区域与内存溢出异常的详细探讨

《Java内存区域与内存溢出异常的详细探讨》:本文主要介绍Java内存区域与内存溢出异常的相关资料,分析异常原因并提供解决策略,如参数调整、代码优化等,帮助开发者排查内存问题,需要的朋友可以参考下... 目录一、引言二、Java 运行时数据区域(一)程序计数器(二)Java 虚拟机栈(三)本地方法栈(四)J

java变量内存中存储的使用方式

《java变量内存中存储的使用方式》:本文主要介绍java变量内存中存储的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、变量的定义3、 变量的类型4、 变量的作用域5、 内存中的存储方式总结1、介绍在 Java 中,变量是用于存储程序中数据

springboot实现配置文件关键信息加解密

《springboot实现配置文件关键信息加解密》在项目配置文件中常常会配置如数据库连接信息,redis连接信息等,连接密码明文配置在配置文件中会很不安全,所以本文就来聊聊如何使用springboot... 目录前言方案实践1、第一种方案2、第二种方案前言在项目配置文件中常常会配置如数据库连接信息、Red

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取