2014年7月29日 buddy分配算法
内核需要为分配一组连续的页框提供一种健壮、高效的分配策略。分配连续的页框必须解决内存管理中的外碎片(external fragmentation)。频繁的请求和释放不同大小的一组连续页框,必然导致分配页框的块分算来许多小块的空闲页框无法被一次性大量分配使用。
linux内核采用著名的伙伴系统算法来解决外碎片问题。该算法的核心思想是把所有的空闲页框分成11个链块表。每个链块表的大小分别为1,2,4,8,16,32,64,128,256,512和1024个连续的页框。
每个块b可以被分成两块b1和b2,假设b1的索引为bi1,b2的索引为bi2,并且由于是块内页框是连续的,则可以对bi1进行与(1<<order(2^order为b块的页框数))异或操作得到bi2,bi2也可以通过相同的方式得到bi1。
每个块的第一个页框物理地址应该是该块大小的整数倍。例如大小为16个页框的块,其起始地址应该为16*2^12(2^12为一个页框大小,4K)的倍数。假设要请求256个页框的块,算法先在256个页框的链表中检查是否有一个空闲块。如果没有,查找下一个更大的页框,也就是512个页框的链表。如果在512个页框的链表里存在这样的块,就把512个页框的块等分成两分,一份用于满足请求,一份插入到256个页框的链表中。如果在512个页框的链表里没有这样的块,就在1024个页框的链表中找。如果1024个页框的链表中有这样的块,就把1024个页框的256个页用于满足请求,把剩余的768个页框中的512个页框块放到大小为512个页框的链表中,并把剩余的256个页框块放入到256个页框的链表中。如果1024个页框的链表里也没有这样的块,分配失败,返回NULL。
在释放的时候通过把页框的索引进行异或操作得到伙伴的索引,通过将伙伴从它目前所在的链表中删除掉达到和伙伴合并的效果。
Linux 2.6 内核阅读笔记 内存管理