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

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

相关文章

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

java获取图片的大小、宽度、高度方式

《java获取图片的大小、宽度、高度方式》文章介绍了如何将File对象转换为MultipartFile对象的过程,并分享了个人经验,希望能为读者提供参考... 目China编程录Java获取图片的大小、宽度、高度File对象(该对象里面是图片)MultipartFile对象(该对象里面是图片)总结java获取图片

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

Linux内存泄露的原因排查和解决方案(内存管理方法)

《Linux内存泄露的原因排查和解决方案(内存管理方法)》文章主要介绍了运维团队在Linux处理LB服务内存暴涨、内存报警问题的过程,从发现问题、排查原因到制定解决方案,并从中学习了Linux内存管理... 目录一、问题二、排查过程三、解决方案四、内存管理方法1)linux内存寻址2)Linux分页机制3)

vscode保存代码时自动eslint格式化图文教程

《vscode保存代码时自动eslint格式化图文教程》:本文主要介绍vscode保存代码时自动eslint格式化的相关资料,包括打开设置文件并复制特定内容,文中通过代码介绍的非常详细,需要的朋友... 目录1、点击设置2、选择远程--->点击右上角打开设置3、会弹出settings.json文件,将以下内

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

Redis多种内存淘汰策略及配置技巧分享

《Redis多种内存淘汰策略及配置技巧分享》本文介绍了Redis内存满时的淘汰机制,包括内存淘汰机制的概念,Redis提供的8种淘汰策略(如noeviction、volatile-lru等)及其适用场... 目录前言一、什么是 Redis 的内存淘汰机制?二、Redis 内存淘汰策略1. pythonnoe