Linux記憶體管理中的slab分配器

2021-10-11 04:05:16 字數 2314 閱讀 6649

linux核心中基於夥伴演算法實現的分割槽頁框分配器適合大塊記憶體的請求,它所分配的記憶體區是以頁框為基本單位的。對於核心中小塊連續記憶體的請求,比如說幾個位元組或者幾百個位元組,如果依然分配乙個頁框來來滿足該請求,那麼這很明顯就是一種浪費,即產生內部碎片(internal fragmentation)

為了解決小塊記憶體的分配,linux核心基於solaris 2.4中的slab分配演算法實現了自己的slab分配器。除此之外,slab分配器另乙個主要功能是作為乙個快取記憶體,它用來儲存核心中那些經常分配並釋放的物件。

slab分配器中用到了物件這個概念,所謂物件就是核心中的資料結構以及對該資料結構進行建立和撤銷的操作。它的基本思想是將核心中經常使用的物件放到快取記憶體中,並且由系統保持為初始的可利用狀態。比如程序描述符,核心中會頻繁對此資料進行申請和釋放。當乙個新程序建立時,核心會直接從slab分配器的快取記憶體中獲取乙個已經初始化了的物件;當程序結束時,該結構所佔的頁框並不會被釋放,而是重新返回slab分配器中。如果沒有基於物件的slab分配器,核心將花費更多的事件去分配、初始化以及釋放乙個物件。

slab分配器有以下三個基本目標:

1.減少夥伴演算法在分配小塊連續記憶體時所產生的內部碎片;

2.將頻繁使用的物件快取起來,減少分配、初始化和釋放物件的事件開銷。

3.通過著色技術調整物件以更好地使用硬體快取記憶體;

slab分配器為每種物件分配乙個快取記憶體,這個快取可以看做是同型別物件的一種儲備。每個快取記憶體所佔的記憶體區又被劃分多個slab,每個slab是由乙個或多個連續的頁框組成。每個頁框中包含若干個物件,既有已經分配的物件,也包含空閒的物件。slab分配器的大致組成圖如下:

每個快取記憶體通過kmem_cache結構來描述,這個結構中包含了對當前快取記憶體各種屬性資訊的描述。所有的快取記憶體通過雙鏈表組織在一起,形成快取記憶體鍊錶cache_chain。每個kmem_cache結構中並不包含對具體slab的描述,而是通過kmem_list3結構組織各個slab。該結構的定義如下:

struct kmem_list3 ;
可以看到,該結構將當前快取中的所有slab分為三個集合: 空閒物件的slab鍊錶slabs_free,非空閒物件的slab鍊錶slabs_full以及部分空閒物件的slab鍊錶slabs_partial。每個slab有相應的slab描述符,即slab結構,它的定義如下:

struct slab ;
slab描述符中的list欄位標明了當前slab處於slab處於三個slab鍊錶的其中乙個。我們將上述的slab分配器進行細化,可以得到下面的結構圖:

slab快取記憶體分為兩大類,普通快取記憶體和專用快取記憶體。普通快取記憶體並不針對核心中特定的物件,它首先會為kmem_cache結構本身提供快取記憶體,這類快取儲存在cache_cache變數中,該變數即代表的是cache_chain鍊錶中的第乙個元素;另一方面,它為核心提供了一種通用快取記憶體。專用快取記憶體是根據核心所需,通過制定具體的物件而建立。

3.1 普通快取記憶體

slab分配器中kmem_cache是用來描述快取記憶體的結構,因此它本身也需要slab分配器對其進行快取記憶體。cache_cache變數儲存著對快取記憶體描述符的快取記憶體。

static struct kmem_cache cache_cache = ;
slab分配器所提供的小塊連續記憶體的分配是通過通用快取記憶體實現的。通用快取記憶體所提供的物件具有幾何分布的大小,範圍為32到131072位元組。核心中提供了kmalloc()和kfree()兩個介面分別進行記憶體的申請和釋放。

3.2 專用快取記憶體

核心為專用快取記憶體的申請和釋放提供了一套完整的介面,根據所傳入的引數為具體的物件分配slab快取。

快取記憶體的申請和釋放

kmem_cache_create()用於對乙個指定的物件建立快取記憶體。它從cache_cache普通快取記憶體中為新的專有快取分配乙個快取記憶體描述符,並把這個描述符插入到快取記憶體描述符形成的cache_chain鍊錶中。kmem_cache_destory()用於撤銷乙個快取記憶體,並將它從cache_chain鍊錶上刪除。

slab的申請和釋放

kmem_cache_alloc()在其引數所指定的快取記憶體中分配乙個slab。相反,kmem_cache_free()在其引數所指定的快取記憶體中釋放乙個slab。

Linux記憶體管理slab分配器

在solaris 2.4以前,linux核心採用基於夥伴演算法實現的分割槽頁框分配器適合大塊記憶體的請求。夥伴將空閒頁面分為m個組,第1組儲存2 0個單位的記憶體塊,第2組儲存2 1個單位的記憶體塊,第3組儲存2 2個單位的記憶體塊,第4組儲存2 3個單位的記憶體塊,以此類推.直到m組.但是夥伴演算...

Linux記憶體管理之slab演算法簡述

slab 分配機制。slab 快取 linux 所使用的 slab 分配器的基礎是 jeff bonwick 為 sunos 作業系統首次引入的一種演算法。jeff 的分配器是圍繞 物件快取進行的。在核心中,會為有限的 物件集 例如 檔案描述符 和其他常見結構 分配大量記憶體。jeff 發現對核心中...

linux記憶體管理 之 slab分配器

1 頁面分配器是頁面級的記憶體分配工具,能分配2的order次冪的連續物理記憶體。linux在頁面級記憶體分配的基礎上,開發了小記憶體分配方案 slab slob slub。後兩者分別針對大型系統和嵌入式系統。2 slab分配器的思想 先利用頁面分配器分配出單個或者一組連續的物理頁面,然後在此基礎上...