2010年(30)
分类: C/C++
2010-06-28 17:37:42
算法
malloc算法中有两部分内容一直没有变化
内存中的所有chunk的头尾中包含他们的大小信息,这些信息有以下重要的功能:
- 相邻的不用的chunk可以组合成一个大的chunk,这将减小一些小的不可用的chunk块
- 根据已知的一个chunk信息可以以正反两个方向遍历所有的chunk块
malloc算法中最开始的版本以这种方式实现了边界标记,因为在一个活动的chunk中不需要使用到尾部字段,因此最近的版本在程序中省略了chunk中的尾部字段,删减它们也减少了内存空间的浪费,但是,缺少这些域对于自身的错误检测是比较不利的。
所有可供使用的chunk块根据不同的大小在chunk箱中保存,因此,这里会有一共128个固定大小的容纳箱,对于小于512字节的容纳箱,他们每个都有一个固定的大小(空间间隔8个字节,简单地以8字节对齐)。收纳箱的查找以最小、最适合为先的顺序,我们知道,与其它通用算法如first-fit比较,这种算法对实际有效负载而言会有更少的碎片,性能更好。在1995之前,容纳箱中的chunk是不进行排序的,因此,只是大体上实现best-fit策略,在近几年的版本中,根据chunk的大小进行了排序。
|
虽然对于已分配或空闲的chunk都使用相同的结构,但是用到的成员却不相同,这点从《Glibc中malloc内存分配内幕》可看到,下面这段话摘自一篇文章,详细说明了堆中分配信息的记录方式:
第一.是通过chunk的头,chunk中的头一个字是记录前一个chunk的大小,第二个字是记录当前chunk的大小和一些标志位,从第三个字开始是要使用的内存。所以通过内存地址可以找到chunk,通过chunk也可以找到内存地址。还可以找到相邻的下一个chunk,和相邻的前一个chunk。一个堆完全是由n个chunk组成。
第二.是由3种队列记录,只用空闲chunk才会出现在队列中,使用的chunk不会出现在队列中。如果内存块是空闲的它会挂到其中一个队列中,它是通过内存复用的方式,使用空闲chunk的第3个字和第4个字当作它的前链和后链(变长块是第5个字和第6个字),省的再分配空间给它。
第一种队列是bins,bins有128个队列,前64个队列是定长的(不超过512字节),每隔8个字节大小的块分配在一个队列,后面的64个队列是不定长的,就是在一个范围长度的都分配在一个队列中。所有长度小于512字节(大约)的都分配在定长的队列中。后面的64个队列是变长的队列,每个队列中的chunk都是从小到大排列的。
第二种队列是unsort队列(只有一个队列),(是一个缓冲)所有free下来的如果要进入bins队列中都要经过unsort队列。
第三种队列是fastbins,大约有10个定长队列,(是一个高速缓冲)所有free下来的并且长度是小于80的chunk就会进入这种队列中。进入此队列的chunk在free的时候并不修改使用位,目的是为了避免被相邻的块合并掉。
|