slab

slab

slab是Linux操作系統的一種內存分配機制,slab分配演演算法採用cache 存儲內核對象。slab 緩存、從緩存中分配和釋放對象然後銷毀緩存的過程必須要定義一個 kmem_cache 對象,然後對其進行初始化這個特定的緩存包含 32 位元組的對象

分配器


slab是Linux操作系統的一種內存分配機制。其工作是針對一些經常分配並釋放的對象,如進程描述符等,這些對象的大小一般比較小,如果直接採用夥伴系統來進行分配和釋放,不僅會造成大量的內存碎片,而且處理速度也太慢。而slab分配器是基於對象進行管理的,相同類型的對象歸為一類(如進程描述符就是一類),每當要申請這樣一個對象,slab分配器就從一個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 緩存
清單1
清單1
使用所分配的 slab 緩存,您可以從中分配一個對象了。清單 2 給出了一個從緩存中分配和釋放對象的例子。它還展示了兩個其他函數的用法。
清單 2. 分配和釋放對象
清單2
清單2
最後,清單 3 演示了 slab 緩存的銷毀。調用者必須確保在執行銷毀操作過程中,不要從緩存中分配對象。
清單 3. 銷毀 slab 緩存
清單3
清單3

優點


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

優勢


對於小型的嵌入式系統來說,存在一個 slab 模擬層,名為 SLOB。這個 slab 的替代品在小型嵌入式 Linux 系統中具有優勢,但是即使它保存了 512KB 內存,依然存在碎片和難於擴展的問題。在禁用 CONFIG_SLAB 時,內核會回到這個 SLOB 分配器中。