8-2.前瞻快取(Lookaside Caches)

驅動需要一次又一次配置許多一樣大小的物件時,利用此機制將相同大小的物件集中在相同的集散區,再從裡面去配置記憶體,驅動程式不必為了刻意使用前瞻快取,而調整自己的記憶體存取行為,但USB以及SCSI此類裝置會使用此機制。 核心裡的快取管理系統,有時被稱為"slab allocator",它的函式宣告於<linux/slab.h>代表快取的記憶體物件型別是kmem_cache_t,透過kmem_cache_create()來建立快取物件。

kmem_cache_t *kmem_cache_create(const char *name,size_t size,size_t offset,unsigned long flags,void (*constructor)(void*,kmem_cache_t *,unsigned long flags),void (*destructor)(void*,kmem_cache_t *,unsigned long flags));

name是一個同時代表函式與快取的符號,可以用來追求問題的資訊 offset是第一個物件在記憶頁的起始位置 flags控制配置方式:

SLAB_NO_REAP

保護快取不因系統短缺記憶體而縮減其容量

SLAB_HWCACHE_ALIGN

此旗標要求每個資料物件都要對齊一條快取線

SLAB_CACHE_DMA

要求每一個資料物件都配置在DMA可存取的記憶體。

constructordestructor兩者都是選擇性引數,前者指向一個負責指向一個負責物件初始化工作的函式,後者所指的函式,會在物件的記憶體被釋放回系統之前被呼叫一次。為了方便可以使用同一個函式來同時兼任建構式與解構式,為了函式知道自己要負責何種任務,slab_allocator會傳遞SLAB_CTOR_CONSTRUCTOR旗標給建構式。在成功建立物件的快取之後,就可以呼叫kmem_cache_alloc()來配置物件:

void *kmem_cache_alloc(kmem_cache_t *cache,int flags);

如果要釋放一個物件,使用kmem_cache_free():

void kmem_cache_free(kmem_cache_t *cache,const void *obj);

當驅動程式使用完快取,可用下函式釋放:

int kmem_cache_destroy(kmem_cache_t *cache);

kmem_cache_destroy()只有在所有從快取配置出去的物件歸還之後,才會成功銷毀快取。

記憶池

核心中有些關鍵情況絕不容許記憶體配置失敗,為了確保這些關鍵情況絕對可配置到,核心開發了一種抽象觀念稱為記憶池(memory pool)。實際上記憶池與前瞻快取很像,唯一差別記憶池總是會保持一些可用的記憶體,以應付緊急狀況。 記憶體的型別為mempool_t(定義於<linux/mempool.h>),可以用mempool_create()建立:

mempool_t *mempool_create(int min_nr,mempool_*alloc_t *alloc_fn,mempool_free_t *free_fn,void *pool_data);

min_nr代表記憶池中至少保留多少個物件配置量。物件的實際配置與釋放,是由alloc_fn與free_fn型別的函式負責,這兩個型別的定義如下:

typedef void *(mempool_alloc_t)(int gfp_mask,void *pool_data);
typedef void *(mempool_free_t)(void *element,void *pool_data);

mempool_create()所收到的最後一個引數(pool_data),會傳給flloc_fn()與free_fn()。

記憶體配置通常可以使用slab allocator來代勞,設定記憶池的程式片段,看起來像下面這樣:

cache = kmem_cache_creat();
pool = mempool_create(MY_POOL_MINIMUN,mempool_alloc_slab,mempool_free_slab,cache);

一旦建立好記憶池後,可用下列這組函式來配置,釋放物件:

void *mempool_alloc(mempool_t *pool,int gfp_mask);
void *mempool_free(void *element,mempool_t *pool);

記憶池容量可於下列函式來改變:

int mempool_resize(mempool_t *pool,int new_min_nr,int gfp_mask);

不再需要記憶池,就將其還給系統:

void mempool_destroy(mempool_t *pool);

results matching ""

    No results matching ""