九:幾點補充:
1: slab
中使用的頁面都會加上「pg_slab」標誌,以跟一般的頁面區別。另外,在釋放記憶體的時候,經常需要用到從頁面到slab的對應轉換關係。那是怎樣標識的呢?
關於標誌:
注意有以下**:
static void *kmem_getpages(kmem_cache_t *cachep, int flags, int nodeid)
…… }
關於從頁面到slab的轉換:
向夥伴系統請求記憶體
static int cache_grow (kmem_cache_t * cachep, int flags)
static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)
while (--i); }
從上面的函式可以看出,pg->lru.next指向它所在的cache pg->lru.prev指向它所在slab
在**中,用slabp = get_page_slab(virt_to_page(objp))來計算物件所在的slab
get_page_slab
定義如下:
#define get_page_slab(pg) ((struct slab *)(pg)->lru.prev)
所以,只要直接取pg的lru.prev即可。
slab
的這部份設計很高效,很巧妙
2:在上述**中,經常用到slab_bufctl的操作,下面就來詳細分析一下:
先來看下cache中的slab大小的計算。即cache的slab_size欄位:
kmem_cache_t * kmem_cache_create (const char *name, size_t size, size_t align,
unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long),
void (*dtor)(void*, kmem_cache_t *, unsigned long))
cachep->num:slab
中的object個數
從上面可以看到,slab_size已經包括了num個kmem_bufctl_t大小,也可以理解成有num個元素的kmem_bufctl_t陣列。實際上kmem_bufctl_t又被定義為:unsigned short
typedef unsigned short kmem_bufctl_t;
slab_bufctl
()用來計算kmem_bufctl_t陣列的首位址。**如下:
static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)
我們接著看一下,kmem_bufctl_t陣列如何被初始化。初始化是在新增乙個slab 的時候,看下相應的**:
static int cache_grow (kmem_cache_t * cachep, int flags)
在對每個物件初始化的時候:
static void cache_init_objs (kmem_cache_t * cachep,
struct slab * slabp, unsigned long ctor_flags)
slab_bufctl(slabp)[i-1] = bufctl_end;
slabp->free = 0; }
初始化之後,kmem_bufctl_t陣列中的值如下圖所示:
從上面的分析可以看到,
slab
中的free
欄位與kmem_bufctl_t
陣列中的值會錯開乙個值。
再來看從
slab
中分配物件的時候:
static void* cache_alloc_refill(kmem_cache_t* cachep, int flags)
…… }
釋放對像的時候:
static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
結合上面的初始化可以看到,有這樣的乙個規律:
kmem_bufctl_t
陣列中的slabp->free項的值就是下乙個空閒對像的序號。結合這一樣就能很好的理解這一部份**了
十:kmalloc()/kfree()的實現
kmalloc/kfree
的實現其實跟上面是所討論的是一樣的,所不同的是。上面討論的是屬於專用cache,這裡所討論的普通cache.也可以這樣說:專用cache是從資料結構方面來管理記憶體的。普通cache是以大小來管理的。
我們在前面曾討論過,slab分配器按大32*(2^0),32*(2^1),32*(2^2) ….32*(2^12)大小,共劃分了13個區域。kmalloc()根據所申請的資料大小,選擇合適的cache分配記憶體
**如下示:
void * __kmalloc (size_t size, int flags)
return null; }
kfree
的實現**:
void kfree (const void *objp)
十一:總結:
slab
分配器中有很多值得仔細研讀的**。與2.4相比,2。6核心新增了兩個緩衝結構,乙個是ac,另乙個是share。有效的緩減了對夥伴系統的壓力
Linux記憶體管理之slab演算法簡述
slab 分配機制。slab 快取 linux 所使用的 slab 分配器的基礎是 jeff bonwick 為 sunos 作業系統首次引入的一種演算法。jeff 的分配器是圍繞 物件快取進行的。在核心中,會為有限的 物件集 例如 檔案描述符 和其他常見結構 分配大量記憶體。jeff 發現對核心中...
linux記憶體管理 之 slab分配器
1 頁面分配器是頁面級的記憶體分配工具,能分配2的order次冪的連續物理記憶體。linux在頁面級記憶體分配的基礎上,開發了小記憶體分配方案 slab slob slub。後兩者分別針對大型系統和嵌入式系統。2 slab分配器的思想 先利用頁面分配器分配出單個或者一組連續的物理頁面,然後在此基礎上...
Linux記憶體管理之slab分配器分析
一 準備知識 前面我們分析過了大記憶體分配的實現機制,事實上,若為小塊記憶體而請求整個頁面,這樣對於記憶體來說是一種極度的浪費。因此linux 採用了slab 來管理小塊記憶體的分配與釋放。slab 最早是由sun 的工程師提出。它的提出是基於以下因素考慮的 1 核心函式經常傾向於反覆請求相同的資料...