本文章的理解参考了文章:https://blog.youkuaiyun.com/qq_22238021/article/details/80208630#commentBox,非常感谢;
Linux内核伙伴算法中每个order 的位图都表示所有的空闲块:
- 位图的某位对应两个伙伴块,为1就表示其中一块忙,为0表示两块都闲或都在使用。
- 系统每次分配和回收伙伴块时都要对它们的伙伴位跟1进行异或运算。
意思是指刚开始时,两个伙伴块都空闲,它们的伙伴位为0,如果其中一块被使用,异或后得1;如果另一块也被使用,异或后得0;如果前面一块回收了异或后得1;如果另一块也回收了异或后得0。
伙伴块:
- 两个快具有相同的大小,记作 a;
- 它们的物理地址是连续的;
- 第一块的第一个页框的物理地址是 2 * a * 2^12 的倍数;
主要用途:
在回收算法中标示是否可以和伙伴块合并,分配时只要搜索空闲链表就足够了。当然,分配的同时还要对相应位异或一下,这是为回收算法服务。
看下分配过程:
例如: 假设有16个页面RAM
-
初始位图
order(0)中,
第一个bit表示开始的2个页面(页面0和页面1均忙,故map位位0),
第二个bit表示接下来的2个页面,以此类推。
因为页面4已分配,而页面5空闲,故第三个bit为1。
order(1)中,
第三个bit是1的原因是一个伙伴完全空闲(页面8和9),和它对应的伙伴(页面10和11)却并非如此。以后回收页面时,可以合并。
order(2)中,
第二个bit是1的原因类似order(1)中的描述; -
分配order=1的空闲空间
步骤:
2.1 初始空闲链表为:
order(0): 5, 10 (空闲块为什么不是5、8、9、10、12、13、14、15)
order(1): 8 [8,9] (空闲块为什么不是8[8,9]、12[12,13]、14[14,15])
order(2): 12 [12,13,14,15]
order(3): 无空闲块
2.2 从上面空闲链表中:
我们可以看出,order(1)链表上,有一个空闲的页面块,把它(第一个空闲的块)分配给用户,并从该链表中删除。分配空闲页块[8,9]; -
再分配order=1的空闲空间
当我们再需要一个order(1)的块时,同样我们从order(1)空闲链表上开始扫描。
若在order(1)上没有空闲页面块,那么我们就到更高的级别(order)上找,order(2)。
此时有一个空闲页面块,该块是从页面12开始。该页面块被分割成两个稍微小一些order(1)的页面块,[12,13]和[14,15]。[14,15]页面块加到order(1)空闲链表中,同时[12,13]页面块返回给用户。
最终空闲链表为:
order(0): 5, 10
order(1): 14 [14,15]
order(2):
order(3):
回收过程:
示例: 假设有16个页面RAM;
- 初始位图
当我们回收页面11(order 0)时,则执行以下步骤:
1.1、找到在order(0)伙伴位图中代表页面11的位,计算使用下面公示:
index = page_idx >> (order + 1)
= 11 >> (1 + 0)
= 5;
1.2、检查上面一步计算位图中相应bit的值。若该bit值为1,则和我们临近的,有一个空闲伙伴。Bit5的值为1(注意是从bit0开始的,Bit5即为第6bit),因为它的伙伴页面10是空闲的。
1.3、现在我们重新设置该bit的值为0,因为此时两个伙伴(页面10和页面11)完全空闲。
1.4、我们将页面10,从order(0)空闲链表中摘除。
1.5、此时,我们对2个空闲页面(页面10和11,order(1))进行进一步操作。
1.6、新的空闲页面是从页面10开始的,于是我们在order(1)的伙伴位图中找到它的索引,看是否有空闲的伙伴,以进一步进行合并操作。使用第一步中的计算公式,我们得到bit 2(第3位)
index = page_idx >> (order + 1)
= 10>>(1+1)
= 3;
1.7、Bit 2(order(1)位图)同样也是1,因为它的伙伴页面块(页面8和9)是空闲的。
1.8、重新设置bit2(order(1)位图)的值为0,然后在order(1)链表中删除该空闲页面块。
1.9、现在我们合并成了4页面大小(从页面8开始[8,9,10,11])的空闲块,从而进入另外的级别。在order(2)中找到伙伴位图对应的bit值(8>>(1+2)),是bit1,且值为1,跟1异或后为0,重置bit1为0,需进一步合并(原因同上)。
1.10、从oder(2)链表中摘除空闲页面块(从页面12开始),进而将该页面块和前面合并得到的页面块进一步合并。现在我们得到从页面8开始,大小为8个页面的空闲页面块[8,9,10,11,12,13,14,15]。
1.11、我们进入另外一个级别,order(3)。它的位索引为0,它的值同样为0。这意味着对应的伙伴不是全部空闲的,所以没有再进一步合并的可能。我们仅设置该bit为1,然后将合并得到的空闲页面块放入order(3)空闲链表中。
1.12最终得到空闲页面如下: