现在的位置: 首页 > 综合 > 正文

内存分配算法之伙伴算法

2013年09月05日 ⁄ 综合 ⁄ 共 6120字 ⁄ 字号 评论关闭

References:

  1. http://blog.csdn.net/zhouzhanglong/archive/2009/04/17/4086349.aspx

Next Fit算法

首先为了作一个对比,使用了一个来自于《C程序设计语言》上面的malloc版本来进行比对。

这个简单版本的思想是使用一个循环单链表来进行空闲块的维护,base变量表示该链表的头,freep表示上次操作的(malloc或者free)的空闲块。

分配一定大小的块的时候,从freep开始找,知道找到一个空闲块其大小大于等于请求块的大小。如果大小刚好,则直接分配出去,否则从尾部开始分配请求大小的块,剩余的大小就变成新的空闲块,这样做的好处是不用维护一个指向freep前一个空闲块的指针,而只需要改变size值就可以。这个算法在操作系统的术语里面叫做Next Fit。

这个算法具有一定的随机性的思想,所以总体来说块的分配会比较平均。

 

以下是malloc.h的内容:

 

下面是malloc和free的函数定义:


Buddy Algorithm(伙伴算法)

就如Reference里面的算法描述,伙伴算法的核心思想是把块的大小都定好,一般是2的幂的大小。

在这里我们会有一个最大的幂值,称为u,也就是最大块就是2^u那么大。

有一个最小幂值,称为l,最小块的大小就是2^l那么大。

然后不同大小的块使用不同的链表来管理,总的是一个free_area的数组来存储这些链表的表头。其中数组free_area里面的下标表示的就是这个链表对应的块的大小的幂数。

然后在分配空闲块的时候首先从最小的大于申请大小的块开始查找。如果这个申请块的幂数是7那么就从free_area[7]开始查找。如果这个链表为空,则往大的链表开始搜索,如果搜索到了的话,将大块分割成两个小块,其中一块用来分配,另外一块用来存在小的块的链表里面。

 

这里我的实现是使用了双向链表来实现。

而在free的过程中,就查看这个释放块的相邻块是否也是空闲,这里相邻块称为伙伴(buddy)。如果伙伴也是在空闲块的块的话,那么就将这两个块合并,这个过程递归,不能再合并为止。

下面是buddy.h里面关于函数的定义:

下面相关的数据结构和函数定义:

 

可以看到伙伴算法对于零散块的处理是比较好的。伙伴算法相对于Next Fit算法的好处是减少了External Fragmentation(外部碎块,也就是在分配块之间的洞),但是增加了Internal Fragmentation(内部碎块,也就是在申请块内部有一部分是没有被用到的)。

 

经过测试,使用了100次随机从20到120的随机大小块分配,然后再随机的从这些分配块里面释放。

得到的结果是Next Fit的碎片数目是16,而Buddy的数目是11。

从这个数字多少可以感受到对于碎片的处理,Buddy的确是优于Next Fit。

抱歉!评论已关闭.