Hi, Buddy !
刺蝟@http://blog.csdn.net/littlehedgehog
關於位元影像
Linux核心夥伴演算法中每個order 的位元影像都表示所有的空閑塊,比如我家的電腦記憶體256M(現在連上個qq首頁都比較卡),理論上的order為0的bitmap有256M/(4K*2)塊。為什麼要除以二呢? 因為 位元影像的某位對應於兩個夥伴塊,為1就表示其中一塊忙,為0表示兩塊都閑。
每次alloc或者free要操作夥伴系統時我們都要異或運算,這是因為 所謂異或,是指剛開始兩塊都閑為0,後來其中一塊用了異或一下得1,後來另一塊也用了異或一下得0,後來前面一塊回收了異或一下得1,後來另一塊也回收了異或一下得0,
這樣(如果為1就不合并)就又可以和前面一塊合并成一大塊了。
位元影像的主要用途是在回收演算法中指示是否可以和夥伴塊合并,分配時只要搜尋空閑鏈表就足夠了。當然,分配的同時還要對相應位異或一下了,這是為回收演算法服務。
關於分配演算法
假設在初始階段,全是大小為2^9大小的塊( MAX_ORDER為10),序號依次為0, 512, 1024等等,並且所有area的map位都為0(實際上作業系統代碼要佔一部分空間,但這裡只是舉例),現在要分配一個2^3大小的頁面塊,有以下動作:
1. 從order為3的area的空閑鏈表開始搜尋,沒找到就向高一級area搜尋,依次類推,按照假設條件,會一直搜尋到order為9的area,找到了序號為0的2^9頁塊。
2. 把序號為0的2^9頁塊從order為9的area的空閑鏈表中摘除並對該area的第0位( 0>>(1+9) )異或一下得1。
3. 把序號為0的2^9頁塊拆分成兩個序號分別為0和256的2^8頁塊,前者放入order為8的area的空閑鏈表中,並對該area的第0位( 0>>(1+8) )異或一下得1。
4. 把序號為256的2^8頁塊拆分成兩個序號分別為256和384的2^7頁塊,前者放入order為7的area的空閑鏈表中,並對該area的第1位( 256>>(1+7) )異或一下得1。
5. 把序號為384的2^7頁塊拆分成兩個序號分別為384和448的2^6頁塊,前者放入order為6的area的空閑鏈表中,並對該area的第3位( 384>>(1+6) )異或一下得1。
6. 把序號為448的2^6頁塊拆分成兩個序號分別為448和480的2^5頁塊,前者放入order為5的area的空閑鏈表中,並對該area的第7位( 448>>(1+5) )異或一下得1。
7. 把序號為480的2^5頁塊拆分成兩個序號分別為480和496的2^4頁塊,前者放入order為4的area的空閑鏈表中,並對該area的第15位( 480>>(1+4) )異或一下得1。
8. 把序號為496的2^4頁塊拆分成兩個序號分別為496和504的2^3頁塊,前者放入order為3的area的空閑鏈表中,並對該area的第31位( 496>>(1+3) )異或一下得1。
9. 序號為504的2^3頁塊就是所求的塊。
關於回收演算法
1. 當回收序號為4的1頁塊時,先找到order為0的area,把該頁面塊加入到該area的空閑鏈表中,然後判斷其夥伴塊(序號為5的1頁塊)的狀態,讀該area (不是其它area !)的map的第2位( 4>>(1+order) ),假設夥伴塊被占,則該位為0(回收4塊前,4、5塊
都忙),現異或一下得1,並不再向上合并。
2. 當回收序號為5的1頁塊時,同理,先找到order為0的area,把該頁面塊加入到該area的空閑鏈表中,然後判斷其夥伴塊(序號為4的1頁塊)的狀態,讀該area的map的第2位(5>>(1+order) ), 這時該位為1(4塊已回收),現異或一下得0,並向上合并,把序
號為4的1頁塊和序號為5的1頁塊從該area的空閑鏈表中摘除,合并成序號為4的2頁塊,並放到order為1的area的空閑鏈表中。同理,此時又要判斷合并後的塊的夥伴塊(序號為6的2頁塊)的狀態,讀該area( order為1的area,不是其它! ) 的map的第1位((4>>(1+order) ),假設夥伴塊在此之前已被回收,則該位為1,現異或一下得0,並向上合并,把序號為4的2頁塊和序號為6的2頁塊從order為1的area的空閑鏈表中摘除,合并成序號為4的4頁塊,並放到order為2的area的空閑鏈表中。然後再判斷其夥伴塊狀態,如此反覆。