分配器
slab是Linux作業系統的一種記憶體分配機制。其工作是針對一些經常分配並釋放的對象,如進程描述符等,這些對象的大小一般比較小,如果直接採用夥伴系統來進行分配和釋放,不僅會造成大量的記憶體碎片,而且處理速度也太慢。而slab分配器是基於對象進行管理的,相同類型的對象歸為一類(如進程描述符就是一類),每當要申請這樣一個對象,slab分配器就從一個slab列表中分配一個這樣大小的單元出去,而當要釋放時,將其重新保存在該列表中,而不是直接返回給夥伴系統,從而避免這些內碎片。slab分配器並不丟棄已分配的對象,而是釋放並把它們保存在記憶體中。當以後又要請求新的對象時,就可以從記憶體直接獲取而不用重複初始化。
對象高速快取的組織如右下圖所示,高速快取的記憶體區被劃分為多個slab,每個slab由一個或多個連續的頁框組成,這些頁框中既包含已分配的對象,也包含空閒的對象。
在cache和object中加入slab分配器,是在時間和空間上的折中方案。
分配算法
slab分配算法採用cache 存儲核心對象。當創建cache 時,起初包括若干標記為空閒的對象。對象的數量與slab的大小有關。開始,所有對象都標記為空閒。當需要核心數據結構的對象時,可以直接從cache 上直接獲取,並將對象初始化為使用。
下面考慮核心如何將slab分配給表示進程描述符的對象。在Linux系統中,進程描述符的類型是struct task_struct ,其大小約為1.7KB。當Linux 核心創建新任務時,它會從cache 中獲得struct task_struct 對象所需要的記憶體。Cache 上會有已分配好的並標記為空閒的struct task_struct 對象來滿足請求。
Linux 的slab 可有三種狀態:
•滿的:slab 中的所有對象被標記為使用。
•空的:slab 中的所有對象被標記為空閒。
•部分:slab 中的對象有的被標記為使用,有的被標記為空閒。
slab 分配器首先從部分空閒的slab 進行分配。如沒有,則從空的slab 進行分配。如沒有,則從物理連續頁上分配新的slab,並把它賦給一個cache ,然後再從新slab 分配空間。
示例用法
下面的代碼片斷展示了創建新 slab 快取、從快取中分配和釋放對象然後銷毀快取的過程。首先,必須要定義一個 kmem_cache 對象,然後對其進行初始化(請參看清單 1)。這個特定的快取包含 32 位元組的對象,並且是硬體快取對齊的(由標誌參數SLAB_HWCACHE_ALIGN 定義)。
清單 1. 創建新 slab 快取
使用所分配的 slab 快取,您可以從中分配一個對象了。清單 2 給出了一個從快取中分配和釋放對象的例子。它還展示了兩個其他函式的用法。
清單 2. 分配和釋放對象
最後,清單 3 演示了 slab 快取的銷毀。調用者必須確保在執行銷毀操作過程中,不要從快取中分配對象。
清單 3. 銷毀 slab 快取
優點
與傳統的記憶體管理模式相比, slab 快取分配器提供了很多優點。
1、核心通常依賴於對小對象的分配,它們會在系統生命周期內進行無數次分配。
2、slab 快取分配器通過對類似大小的對象進行快取而提供這種功能,從而避免了常見的碎片問題。
3、slab 分配器還支持通用對象的初始化,從而避免了為同一目的而對一個對象重複進行初始化。
4、slab 分配器還可以支持硬體快取對齊和著色,這允許不同快取中的對象占用相同的快取行,從而提高快取的利用率並獲得更好的性能。
優勢
對於小型的嵌入式系統來說,存在一個 slab 模擬層,名為 SLOB。這個 slab 的替代品在小型嵌入式 Linux 系統中具有優勢,但是即使它保存了 512KB 記憶體,依然存在碎片和難於擴展的問題。在禁用 CONFIG_SLAB 時,核心會回到這個 SLOB 分配器中。