1. 程式人生 > >夥伴演算法和Slab機制

夥伴演算法和Slab機制

夥伴演算法(Buddy)

1,為什麼使用夥伴演算法

        記憶體碎片:記憶體被分割成很小很小的一些塊,這些塊雖然是空閒的,但是卻小到無法使用。隨著申請和釋放次數的增加,記憶體將變得越來越不連續。最後,整個記憶體將只剩下碎片,即使有足夠的空閒頁框可以滿足請求,但要分配一個大塊的連續頁框就可能無法滿足,所以減少記憶體浪費的核心就是儘量避免產生記憶體碎片。為了避免出現這種情況,Linux核心中引入了夥伴系統演算法(buddy system)。

2,基本原理

Buddy(夥伴的定義):

這裡給出夥伴的概念,滿足以下三個條件的稱為夥伴: 1)兩個塊大小相同; 2)兩個塊地址連續; 3)兩個塊必須是同一個大塊中分離出來的;

分配原理:

        夥伴系統將所有的空閒頁框分組為11個塊連結串列,每個塊連結串列分別包含大小為1,2,4,8,16,32,64,128,256,512和1024個連續頁框的頁框塊。假如現在需要4個頁面大小的記憶體塊,該演算法就到free_area[2]中查詢,如果連結串列中有空閒塊,就直接從中摘下並分配出去。如果沒有,演算法將順著陣列向上查詢free_area[3],如果free_area[3]中有空閒塊,那麼將該空閒塊分成相等的兩部分,一部分分配出去,另一部分放入free_area[2]中,如此重複尋找和分配,若到達陣列最後也沒有空閒塊,則放棄分配。

釋放原理:

記憶體的釋放就是分配的逆過程。噹噹釋放一個塊時,先在其對應的連結串列中考查是否有夥伴存在,如果沒有夥伴塊,就直接把要釋放的塊掛入連結串列頭;如果有,則從連結串列中摘下夥伴,合併成一個大塊,然後繼續考察合併後的塊在更大一級連結串列中是否有夥伴存在,直到不能合併或者已經合併到了最大的塊

夥伴系統的缺點

       雖然夥伴系統能夠減少記憶體碎片的產生,但是在linux核心中夥伴系統用來管理實體記憶體,其分配的單位是頁,如果針對一些經常分配並釋放的物件如程序描述符等,這些物件的大小一般比較小,如果直接採用夥伴系統來進行分配和釋放,不僅會造成大量的內碎片,而且處理速度也太慢

Slab機制

        在linux核心中夥伴系統用來管理實體記憶體,其分配的單位是頁,但是向用戶程式一樣,核心也需要動態分配記憶體,而夥伴系統分配的粒度又太大。由於核心無法藉助標準的C庫,因而需要別的手段來實現核心中動態記憶體的分配管理,linux採用的是slab分配器。其工作是針對一些經常分配並釋放的物件,如程序描述符等,這些物件的大小一般比較小,如果直接採用夥伴系統來進行分配和釋放,不僅會造成大量的內碎片,而且處理速度也太慢。而slab分配器是基於物件進行管理的,相同型別的物件歸為一類(如程序描述符就是一類),每當要申請這樣一個物件,slab分配器就從一個slab列表中分配一個這樣大小的單元出去,而當要釋放時,將其重新儲存在該列表中,而不是直接返回給夥伴系統,從而避免這些內碎片。slab分配器並不丟棄已分配的物件,而是釋放並把它們儲存在記憶體中。當以後又要請求新的物件時,就可以從記憶體直接獲取而不用重複初始化。 

Linux 的slab 可有三種狀態:  滿的:slab 中的所有物件被標記為使用。  空的:slab 中的所有物件被標記為空閒。  部分:slab 中的物件有的被標記為使用,有的被標記為空閒。 slab 分配器首先從部分空閒的slab 進行分配。如沒有,則從空的slab 進行分配。如沒有,則從物理連續頁上分配新的slab,並把它賦給一個cache ,然後再從新slab 分配空間。

與傳統的記憶體管理模式相比, slab 快取分配器提供了很多優點。 1、核心通常依賴於對小物件的分配,它們會在系統生命週期內進行無數次分配。 2、slab 快取分配器通過對類似大小的物件進行快取而提供這種功能,從而避免了常見的碎片問題。 3、slab 分配器還支援通用物件的初始化,從而避免了為同一目的而對一個物件重複進行初始化。 4、slab 分配器還可以支援硬體快取對齊和著色,這允許不同快取中的物件佔用相同的快取行,從而提高快取的利用率並獲得更好的效能。