Linux 記憶體管理: Kmalloc

發表於2015-09-22

這裡只說實體記憶體管理 linux核心的,看了很多講解的記憶體的東西,但是自己總結的時候總感覺無從下手,這裡就從實際實體記憶體分配介面開始吧。

Kmalloc 它分配連續的實體記憶體空間 ,它不負責把分配的記憶體空間清零,它能分配多大的呢?並且它只能分配ZONE_NORMAL的不能分配dma和high裡的,也就是隻分配低端記憶體.一般情況下記憶體被分為三個zone:NORMAL、DMA、HIGH.

這個函式是建立在slab分配器的基礎上的,通過cache 而cache有通過slab 分配obj 。

在開始分析kmalloc函式之前,我們需要說明一下linux核心實體記憶體的分配函式API:

__get_free_pages它會呼叫alloc_pages,它的特點是不能從HIGHMEM分配記憶體,分配2的冪個連續物理頁面。它有簡化模式(只分配一page)
__get_free_page,而get_zeroed_page介面分配的頁面內容對應填充為0. 從dma分配可以呼叫__get_dma_pages(它本質也是呼叫__get_free_pages)

那麼終極介面alloc_pages它可以從任何zone裡申請記憶體,當然前提設定對應的flags.

參考核心:linux3.18.13
參考書籍:《linux核心設計與實現》《linux裝置驅動程式》《深入理解linux裝置驅動核心機制》

下面我們就說說kmalloc:(關於分配時候的flags這裡不討論,具體可以參考資料)

我們先看標頭檔案
#include
而關於它的具體實現我們看slab.h中

一般系統預設#include

這裡可以補充下程式碼關於kmalloc_sizes.h

我們看到函式開頭需要說明一下:
__builtin_constant_p 是編譯器gcc內建函式,用於判斷一個值是否為編譯時常量,如果是常數,函式返回1 ,否則返回0。此內建函式的典型用法是在巨集中用於手動編譯時優化顯然如果size為常數 則用__kmalloc(size, flags);申請記憶體.

它查詢需要分配的記憶體在哪個系統cache然後呼叫

我們看具體程式碼:

它實際的分配是slab_alloc:

 

它呼叫objp = __do_cache_alloc(cachep, flags); 除了檢查一些標誌等繼續呼叫
____cache_alloc(cachep, flags);

它是一個統一的介面 (有檢測numa和uma ,linux預設是uma 除非指定了numa)

這裡我們假定是第一次使用分配記憶體,那麼根據在kmem_cache_init中的malloc_sizes[]的初始化,在kmalloc的時候返回的kmalloc_cache指標指向的cache中用到這樣個函式:

我們知道不論array被賦了什麼值,最後都要初始化avail等值.

所以如果array不可用,那麼就會呼叫;當然如果array可用那麼直接返回申請的obj的記憶體指標.

由於第一次使用nodelist上slab連結串列都為空,所以must_grow

它呼叫cache_grow,這個函式首先計算了slab著色處理。然後呼叫kmem_getpages申請page,大小根據cache->gfporder,它返回申請pages的虛擬地址.

而關於slab著色跟硬體緩衝有關,為了儘量避免快取衝突不命中問題,提高效率(cache_line問題)。可以參考《深入理解計算機系統》。

具體操作見:

我們看看另外一個很重要的操作:

相關文章