6.slab層
為了便於資料的頻繁分配和回收,Linux核心提供了slab層(也就是所謂的slab分配器)。slab分配器扮演了通用資料結構緩衝層的角色。
slab層把不同的對象劃分為所謂快取(cache)組,其中每個快取都存放不同類型的對象。這些快取又被劃分為slab,slab由一個或多個物理上連續的頁組成。一般情況下,slab也就僅僅由一頁組成。每個調整緩衝可以由多個slab組成。
每個slab都包含一些對象成員,這裡的對象指的是被緩衝的資料結構。每個slab處於三種狀態之一:滿、部分滿或空。每個快取都是用 kmem_cache_s 結構來表示。這個結構包含三個鏈表 slabs_full,slabs_partial 和 slabs_empty,均存放在 kmem_lists 結構內。這些鏈表包含快取中的所有slab。slab描述符 struct slab 用來描述每個slab:
struct slab { struct list_head list; /* 滿、部分滿或空鏈表 */ unsigned long colouroff; /* slab 著色的位移量 */ void *s_mem; /* 在 slab 中的第一個對象 */ unsigned int inuse; /* 已指派的對象數 */ kmem_bufctl_t tree; /* 第一個空間對象(如果有的話) */};
一個新的快取是通過以下函數建立:
kmem_cache_t *kmem_cache_create( const char *name, /* 存放著快取的名字 */ size_t size, /* 快取中每個元素的大小 */ size_t align, /* 快取內第一個對象的位移,通常0可以滿足要求 */ unsigned long flags, /* 控制快取的行為,可以為0,或者標誌組合 */ void (*ctor)( void *, kmem_cache_t *, unsigned long ), /* 建構函式 */ void (*dtor)( void *, kmem_cache_t *, unsigned long )); /* 解構函式 */
kmem_cache_create 在成功時會返回一個指向所建立快取的指標,否則,返回 NULL。這個函數不能在中斷上下文中調用,因為它可能會睡眠。
要銷毀一個快取,則調用:
int kmem_cache_destroy( kmem_cache_t *cachep );
調用該函數之前必須確儲存在以下兩個條件:
1)快取中的所有slab都必須為空白。
2)在調用 kmem_cache_destroy 期間不再訪問這個快取,調用者必須確保這種同步。
該函數成功執行,返回0;否則,返回非0值。
建立快取之後,就可以通過下列函數從中擷取對象:
void *kmem_cache_alloc( kmem_cache_t *cachep, int flags );
該函數從給定的快取 cachep 中返回一個指向對象的指標,如果快取的所有 slab 中都沒有空間的對象,那麼 slab層必須通過 kmem_getpages 擷取新的頁,flags的值傳遞給 __get_free_pages。應該使用 GFP_KERNEL 或 GFP_ATOMIC。
釋放一個對象,並把它返回給原先的slab,可以使用下面這個函數:
void kmem_cache_free( kmem_cache_t *cachep, void *objp);