slab分配器是Linux內存管理中非常重要和復雜的一部分,其工作是針對一些經常分配並釋放的對象,如進程描述符等,這些對象的大小一般比較小,如果直接采用伙伴系統來進行分配和釋放,不僅會造成大量的內碎片,而且處理速度也太慢。而slab分配器是基於對象進行管理的,相同類型的對象歸為一類(如進程描述符就是一類),每當要申請這樣一個對象,slab分配器就從一個slab列表中分配一個這樣大小的單元出去,而當要釋放時,將其重新保存在該列表中,而不是直接返回給伙伴系統。slab分配對象時,會使用最近釋放的對象內存塊,因此其駐留在CPU高速緩存的概率較高。
相關閱讀:Linux Slab分配器(二)--初始化 http://www.linuxidc.com/Linux/2012-06/62966.htm
用於描述和管理cache的數據結構是struct kmem_cache
- struct kmem_cache {
- /* 1) per-cpu data, touched during every alloc/free */
- /*per-CPU數據,記錄了本地高速緩存的信息,也用於跟蹤最近釋放的對象,每次分配和釋放都要直接訪問它*/
- struct array_cache *array[NR_CPUS];
- /* 2) Cache tunables. Protected by cache_chain_mutex */
- unsigned int batchcount; /*本地高速緩存轉入或轉出的大批對象數量*/
- unsigned int limit; /*本地高速緩存中空閒對象的最大數目*/
- unsigned int shared;
-
- unsigned int buffer_size;/*管理對象的大小*/
- u32 reciprocal_buffer_size;/*buffer_size的倒數值*/
- /* 3) touched by every alloc & free from the backend */
-
- unsigned int flags; /* 高速緩存的永久標識*/
- unsigned int num; /* 一個slab所包含的對象數目 */
-
- /* 4) cache_grow/shrink */
- /* order of pgs per slab (2^n) */
- unsigned int gfporder; /*一個slab包含的連續頁框數的對數*/
-
- /* force GFP flags, e.g. GFP_DMA */
- gfp_t gfpflags; /*與伙伴系統交互時所提供的分配標識*/
-
- size_t colour; /* 顏色的個數*/
- unsigned int colour_off; /* 著色的偏移量 */
-
- /*如果將slab描述符存儲在外部,該指針指向存儲slab描述符的cache,
- 否則為NULL*/
- struct kmem_cache *slabp_cache;
- unsigned int slab_size; /*slab管理區的大小*/
- unsigned int dflags; /*動態標識*/
-
- /* constructor func */
- void (*ctor)(void *obj); /*創建高速緩存時的構造函數指針*/
-
- /* 5) cache creation/removal */
- const char *name; /*高速緩存名*/
- struct list_head next; /*用於將高速緩存鏈入cache chain*/
-
- /* 6) statistics */
- #ifdef CONFIG_DEBUG_SLAB /*一些用於調試用的變量*/
- unsigned long num_active;
- unsigned long num_allocations;
- unsigned long high_mark;
- unsigned long grown;
- unsigned long reaped;
- unsigned long errors;
- unsigned long max_freeable;
- unsigned long node_allocs;
- unsigned long node_frees;
- unsigned long node_overflow;
- atomic_t allochit;
- atomic_t allocmiss;
- atomic_t freehit;
- atomic_t freemiss;
-
- /*
- * If debugging is enabled, then the allocator can add additional
- * fields and/or padding to every object. buffer_size contains the total
- * object size including these internal fields, the following two
- * variables contain the offset to the user object and its size.
- */
- int obj_offset;
- int obj_size;
- #endif /* CONFIG_DEBUG_SLAB */
-
- /*
- * We put nodelists[] at the end of kmem_cache, because we want to size
- * this array to nr_node_ids slots instead of MAX_NUMNODES
- * (see kmem_cache_init())
- * We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache
- * is statically defined, so we reserve the max number of nodes.
- */
- /*struct kmem_list3用於組織該高速緩存中的slab*/
- struct kmem_list3 *nodelists[MAX_NUMNODES];
- /*
- * Do not add fields after nodelists[]
- */
- };
- struct kmem_list3 {
- struct list_head slabs_partial;/*slab鏈表,包含空閒對象和已分配對象的slab描述符*/
- struct list_head slabs_full; /*slab鏈表,只包含非空閒的slab描述符*/
- struct list_head slabs_free; /*slab鏈表,只包含空閒的slab描述符*/
- unsigned long free_objects; /*高速緩存中空閒對象的個數*/
- unsigned int free_limit; /*空閒對象的上限*/
- unsigned int colour_next; /*下一個slab使用的顏色*/
- spinlock_t list_lock;
- struct array_cache *shared; /* shared per node */
- struct array_cache **alien; /* on other nodes */
- unsigned long next_reap; /* updated without locking */
- int free_touched; /* updated without locking */
- };