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

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如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

一文详解SQL Server如何跟踪自动统计信息更新

《一文详解SQLServer如何跟踪自动统计信息更新》SQLServer数据库中,我们都清楚统计信息对于优化器来说非常重要,所以本文就来和大家简单聊一聊SQLServer如何跟踪自动统计信息更新吧... SQL Server数据库中,我们都清楚统计信息对于优化器来说非常重要。一般情况下,我们会开启"自动更新

Python如何获取域名的SSL证书信息和到期时间

《Python如何获取域名的SSL证书信息和到期时间》在当今互联网时代,SSL证书的重要性不言而喻,它不仅为用户提供了安全的连接,还能提高网站的搜索引擎排名,那我们怎么才能通过Python获取域名的S... 目录了解SSL证书的基本概念使用python库来抓取SSL证书信息安装必要的库编写获取SSL证书信息

Win32下C++实现快速获取硬盘分区信息

《Win32下C++实现快速获取硬盘分区信息》这篇文章主要为大家详细介绍了Win32下C++如何实现快速获取硬盘分区信息,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实现代码CDiskDriveUtils.h#pragma once #include <wtypesbase

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

Golang基于内存的键值存储缓存库go-cache

《Golang基于内存的键值存储缓存库go-cache》go-cache是一个内存中的key:valuestore/cache库,适用于单机应用程序,本文主要介绍了Golang基于内存的键值存储缓存库... 目录文档安装方法示例1示例2使用注意点优点缺点go-cache 和 Redis 缓存对比1)功能特性

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C

MySQL8.0设置redo缓存大小的实现

《MySQL8.0设置redo缓存大小的实现》本文主要在MySQL8.0.30及之后版本中使用innodb_redo_log_capacity参数在线更改redo缓存文件大小,下面就来介绍一下,具有一... mysql 8.0.30及之后版本可以使用innodb_redo_log_capacity参数来更改

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

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

golang内存对齐的项目实践

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