转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd
作者联系方式:李先静
<xianjimli at hotmail dot com>
更新时间:
2007-7-9
作为一个
C
程序员,每天都在和
malloc/free/calloc/realloc
系列函数打交道。也许和它们混得太熟了,反而忽略了它们的存在,甚至有了三五年的交情,仍然对它们的实现一无所知。相反,一些好奇心未泯的新手,对它们的实现有着浓厚的兴趣。当初正是一个新同事的问题,促使我去研究内存管理算法的实现。
内存管理算法多少有些神秘,我们很少想着去实现自己的内存管理算法,这也难怪:有这样需求的情况并不多。其实,至于内存分配算法的实现,说简单也简单,说复杂也复杂。要写一个简单的,或许半天时间就可以搞掂,而要写一个真正实用的,可能要花上你几周甚至几个月的时间。
malloc
和
free
是两个核心函数,而
calloc
和
realloc
之所以存在,完全是为了提高效率的缘故。否则完全可以用
malloc
和
free
的组合来模拟它们。
拿
calloc
函数的实现来说,在
32
位机上,内存管理器保证内存至少是
4
字节对齐的,其长度也会扩展到能被
4
字节整除,那么其清零算法就可以优化。可以一次清零
4
个字节,这大大提高清零速度。
拿
realloc
函数的实现来说,如果
realloc
的指针后面有足够的空间,内存管理器可以直接扩展其大小,而无须拷贝原有内容。当然,新大小比原来还小时,更不拷贝了。相反,通过
malloc
和
free
来实现
realloc
时,两种情况下都要拷贝,效率自然会低不少。
另外还有两个非机标准的,但很常用的函数,也涉及到内存分配:
strdup
和
strndup
。这两个函数在
linux
和
win32
下都支持,非常方便。这完全可以用
malloc
来模拟,而且没有性能上的损失。
这里我们主要关注
malloc
和
free
两个函数的实现,并以
glibc 2.3.5(32
位
linux)
为例分析。
内存管理器的目标
内存管理器为什么难写?在设计内存管理算法时,要考虑什么因素?管理内存这是内存管理器的功能需求。正如设计其它软件一样,质量需求一样占有重要的地位。分析内存管理算法之前,我们先看看对内存管理算法的质量需求有哪些:
l
最大化兼容性
要实现内存管理器时,先要定义出分配器的接口函数。接口函数没有必要标新立异,而是要遵循现有标准
(
如
POSIX
或者
Win32)
,让使用者可以平滑的过度到新的内存管理器上。
l
最大化可移植性
通常情况下,内存管理器要向
OS
申请内存,然后进行二次分配。所以,在适当的时候要扩展内存或释放多余的内存,这要调用
OS
提供的函数才行。
OS
提供的函数则是因平台而异,尽量抽象出平台相关的代码,保证内存管理器的可移植性。
l
浪费最小的空间
内存管理器要管理内存,必然要使用自己一些数据结构,这些数据结构本身也要占内存空间。在用户眼中,这些内存空间毫无疑问是浪费掉了,如果浪费在内存管理器身的内存太多,显然是不可以接受的。
内存碎片也是浪费空间的罪魁祸首,若内存管理器中有大量的内存碎片,它们是一些不连续的小块内存,它们总量可能很大,但无法使用,这也是不可以接受的。
l
最快的速度
内存分配
/
释放是常用的操作。按着
2/8
原则,常用的操作就是性能热点,热点函数的性能对系统的整体性能尤为重要。
l
最大化可调性(以适应于不同的情况)
内存管理算法设计的难点就在于要适应用不同的情况。事实上,如果缺乏应用的上下文,是无法评估内存管理算法的好坏的。可以说在任何情况下,专用算法都比通用算法在时
/
空性能上的表现更优。
为每种情况都写一套内存管理算法,显然是不太合适的。我们不需要追求最优算法,那样代价太高,能达到次优就行了。设计一套通用内存管理算法,通过一些参数对它进行配置,可以让它在特定情况也有相当出色的表现,这就是可调性。
l
最大化局部性
(Locality)
大家都知道,使用
cache
可以提高程度的速度,但很多人未必知道
cache
使程序速度提高的真正原因。拿
CPU
内部的
cache
和
RAM
的访问速度相比,速度可能相差一个数量级。两者的速度上的差异固然重要,但这并不是提高速度的充分条件,只是必要条件。
另外一个条件是程序访问内存的局部性
(Locality)
。大多数情况下,程序总访问一块内存附近的内存,把附近的内存先加入到
cache
中,下次访问
cache
中的数据,速度就会提高。否则,如果程序一会儿访问这里,一会儿访问另外一块相隔十万八千里的内存,这只会使数据在内存与
cache
之间来回搬运,不但于提高速度无益,反而会大大降低程序的速度。
因此,内存管理算法要考虑这一因素,减少
cache miss
和
page fault
。
l
最大化调试功能
作为一个
C/C++
程序员,内存错误可以说是我们的噩梦,上一次的内存错误一定还让你记忆犹新。内存管理器提供的调试功能,强大易用,特别对于嵌入式环境来说,内存错误检测工具缺乏,内存管理器提供的调试功能就更是不可或缺了。
l
最大化适应性
前面说了最大化可调性,以便让内存管理器适用于不同的情况。但是,对于不同情况都要去调设置,无疑太麻烦,是非用户友好的。要尽量让内存管理器适用于很广的情况,只有极少情况下才去调设置。
设计是一个多目标优化的过程,有些目标之间存在着竞争。如何平衡这些竞争力是设计的难点之一。在不同的情况下,这些目标的重要性又不一样,所以根本不存在一个最好
的内存分配算法。
关于
glibc
的内存分配器,我们并打算做代码级分析,只谈谈几点有趣的东西:
1.
Glibc
分配算法概述:
l
小于等于
64
字节:用
pool
算法分配。
l
64
到
512
字节之间:在最佳凭配算法分配和
pool
算法分配中取一种合适的。
l
大于等于
512
字节:用最佳凭配算法分配。
l
大于等于
128K
:直接调用
OS
提供的函数
(
如
mmap)
分配。
2.
Glibc
扩展内存的方式:
l
int brk(void *end_data_segment);
本函数用于扩展堆空间(堆空间的定义可参考内存模型一章),用
end_data_segment
指明堆的结束地址。
l
void *sbrk(ptrdiff_t increment);
本函数用于扩展堆空间(堆空间的定义可参考内存模型一章),用
increment
指定要增加的大小。
l
void*
mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);
本函数用于分配大块内存了,如前面所述大于
128K
的内存。
3.
空指针和零长度内存
l
free(NULL)
会让程序
crash
吗?答案是不会,标准
C
要求
free
接受空指针,然后什么也不做。
l
malloc(0)
会分配成功吗?答案是会的,它会返回一块最小内存给你。
4.
对齐与取整
l
内存管理器会保证分配出来的内存地址是对齐的,通常是
4
或
8
字节对齐。
l
内存管理器会对要求内存长度取整,让内存长度能被
4
或
8
的整除。
5.
已经分配内存的结构
如果前面有一块有效内存块的,则第一个
size_t
指明前一块内存的大小。
第二个
size_t
指明自己的大小,同时还指明:自己是不是用
mmap
分配的
(M)
,前面是否有一个效内存块(
P
)。你可能觉得奇怪,在
32
位机上,
sizeof(size_t)
就是
32
位,怎么还能留下两个位来保存标志呢?前面我们说了,会对内存长度取整,保证最低
2
或
3bits
为
0
,即是空闲的。
6.
空闲内存的管理
由此可以看出,最小内存块的长度为
16
字节:
sizeof(size_t) +
sizeof(size_t) +
sizeof(void*) +
sizeof(void*) +
0
这一招非常管用,第一次看到时,感觉简直太巧妙了。这使得无需要额外的内存来管理空闲块,利用空闲块自己,把空闲块强制转换成一个双向链表就行了。
相关推荐
内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理.EXE内存清理...
安卓手机内存清理 开源版,包括内存加速,垃圾清理,自启管理,软件管理等。 说明 >现修复android5.0以上不能查看进程的问题,暂时不能支持7.0的查看进程的功能,欢迎各位提出相应的意见或建议,如不能配置好环境,...
内存整理工具 释放内存 清理内存 内存整理工具 释放内存 清理内存 超级兔子内存工具
内存清理工具,可设置灵活内存清理水准大小,加快内存清理
罗技鼠标-板载内存管理器 针对接收器失效或者需重新配对的,可以使用
内存清理工具挂件
超级精炼的内存清理工具,超级精炼的内存清理工具
wince内存清理工具,定期内存清理,方便快捷
清理内存的一个Demo 轻巧实用 初学者最好例子
内存清理工具是一款清理电脑内存垃圾的软件,能够自动智能清理并释放内存,让你的电脑时时刻刻运行流畅,有需要的朋友快下载使用吧。 内存清理工具介绍: 内存清理工具是一款好用的内存自动释放优化工具!电脑运行...
内存清理工具,当内存较小时,安装软件显示内存不够,可以用这个小工具帮助你清除内存碎片,我曾经在256内存计算机上装虚拟机,虚拟机上装Win2000Server获得成功。
实用内存清理程序,一个绝对意想不到的算法,可以实现快速的清理内存垃圾,以及实现内存的管理。
• 设计一个内存管理器,支持至少两种分配策略, 如first-fit,next-fit, best-fit, worst-fit等。 • 对不同分配策略的性能进行评估。 .2 内存管理器 内存管理器的功能是管理物理内存,在我们的实验中,它是用来对...
最强大的内存清理工具--------内存扫把
一款很好的内存清理工具,可以清理内存垃圾文件,腾出内存空间
很多时候android原生的控件都不能满足我们的需求,比如说我们要实现一个内存清理按钮,这时就需要我们自定义一个控件了。
Mem.Reduct.3.3.5 电脑内存清理软件,一键清理满载的内存,恢复流畅,德芙顺滑Mem.Reduct.3.3.5 电脑内存清理软件,一键清理满载的内存,恢复流畅,德芙顺滑Mem.Reduct.3.3.5 电脑内存清理软件,一键清理满载的内存...
win-内存清理工具,不是调用伤害硬盘的API的方式,是 Windows自带清理工具 ,unity3d C# 均可用
开机时间长,机器就会变慢。 用内存清理工具点一下省的重启了。