水平有限,描述不當之處還請之處,轉載請註明出處http://blog.csdn.net/vanbreaker/article/details/7694648
Slab分配器一直處於內核內存管理的核心地位,儘管如此,它還是擁有自身的缺點,最明顯的兩點就是複雜性和過多的管理數據造成的內存上的開銷。針對這些問題,linux引入了slub分配器,slub分配器保留了slab分配器的所有接口,實際上slub分配器的模型和slab分配的模型是基本一致的,只不過在一些地方進行了精簡,這也使得slub分配器工作起來更爲遊刃有餘。兩者主要的區別如下:
- slab分配器爲了增加分配速度,引入了一些管理數組,如slab管理區中的kmem_bufctl數組和緊隨本地CPU結構後面的用來跟蹤最熱空閒對象的數組,這些結構雖然加快了分配對象的速度,但也增加了一定的複雜性,而且隨着系統變得龐大,其對內存的開銷也越明顯。而slub分配器則完全摒棄了這些管理數據,個人覺得這也是slub分配器最精髓的地方,至於slub分配器的具體做法是怎樣的,後面再做分析;
- slab分配器針對每個緩存,根據slab的狀態劃分了3個鏈表--full,partial和free. slub分配器做了簡化,去掉了free鏈表,對於空閒的slab,slub分配器選擇直接將其釋放;
- slub分配器摒棄了slab分配器中的着色概念,在slab分配器中,由於顏色的個數有限,因此着色也無法完全解決slab之間的緩存行衝突問題,考慮到着色造成了內存上的浪費,slub分配器沒有引入着色;
- 在NUMA架構的支持上,slub分配器也較slab分配器做了簡化。
下面來看slub分配器涉及到的主要數據結構
緩存描述結構:
struct kmem_cache {
/* Used for retriving partial slabs etc */
unsigned long flags; /* cache屬性的描述標識 */
int size; /* 分配給對象的內存大小,可能大於實際對象的大小 */
int objsize; /* 對象的實際大小 */
int offset; /* 存放空閒對象的偏移,以字節爲單位 */
struct kmem_cache_order_objects oo;/* oo用來存放分配給slab的頁框的階數(高16位)和
slab中的對象數量(低16位) */
/*
* Avoid an extra cache line for UP, SMP and for the node local to
* struct kmem_cache.
*/
struct kmem_cache_node local_node;/* 本地節點的slab信息 */
/* Allocation and freeing of slabs */
struct kmem_cache_order_objects max;
struct kmem_cache_order_objects min;
gfp_t allocflags; /* 分配時用的GFP標識 */
int refcount; /* 緩存中存在的對象種類數目,因爲slub允許緩存複用,
因此一個緩存中可能存在多種對象類型 */
void (*ctor)(void *); /* 創建對象的構造函數 */
int inuse; /* 元數據的偏移 */
int align; /* 對齊值 */
unsigned long min_partial;/* partial slab鏈表中的最小slab數目 */
const char *name; /* 緩存名 */
struct list_head list; /* 用於將緩存鏈入slab_caches全局緩存鏈表 */
#ifdef CONFIG_SLUB_DEBUG
struct kobject kobj; /* For sysfs */
#endif
#ifdef CONFIG_NUMA
/*
* Defragmentation by allocating from a remote node.
*/
int remote_node_defrag_ratio; /* 該值越小,越傾向於從本節點分配對象 */
struct kmem_cache_node *node[MAX_NUMNODES];/* NUMA架構下每個節點對應的slab信息 */
#endif
#ifdef CONFIG_SMP
struct kmem_cache_cpu *cpu_slab[NR_CPUS]; /* SMP系統下每個CPU對應的slab信息 */
#else
struct kmem_cache_cpu cpu_slab; /* 單核系統下CPU對應的slab信息 */
#endif
};
節點的slab信息描述結構:
struct kmem_cache_node {
spinlock_t list_lock; /* Protect partial list and nr_partial */
unsigned long nr_partial; /* partial slab鏈表中slab的數量 */
struct list_head partial; /* partial slab鏈表表頭*/
#ifdef CONFIG_SLUB_DEBUG
atomic_long_t nr_slabs; /* 節點中的slab數 */
atomic_long_t total_objects; /* 節點中的對象數 */
struct list_head full; /* full slab鏈表表頭 */
#endif
};
本地CPU的slab信息描述結構:
struct kmem_cache_cpu {
void **freelist; /* 指向本地CPU的第一個空閒對象 */
struct page *page; /* 分配給本地CPU的slab的頁框 */
int node; /* 頁框所處的節點,值爲-1時表示DEBUG */
unsigned int offset; /* 空閒對象指針的偏移,以字長爲單位 */
unsigned int objsize; /* 對象的大小 */
#ifdef CONFIG_SLUB_STATS
unsigned stat[NR_SLUB_STAT_ITEMS];/*用以記錄slab的狀態*/
#endif
};
用下圖可以描述這些slub分配器的核心數據結構之間的關係
至此已大概介紹了slub分配器的一些概念和涉及到的核心數據結構,具體的實現細節和原理在後面分析各個部分的代碼時再做交代!