1,基本原理以及重要的数据结构
struct kmem_cache
slub把内存分组管理,每个组分别包含2^3、2^4、...2^11个字节,在4K页大小的默认情况下,另外还有两个特殊的组,分别是96B和192B,共11组。每一个组都是用一个kmalloc_cache[]数组表示的。每个数组元素对应一种大小的内存,可以把一个kmem_cache结构体看做是一个特定大小内存的零售商,整个slub系统中共有12个这样的零售商,每个“零售商”只“零售”特定大小的内存,例如:有的“零售商”只"零售"8Byte大小的内存,有的只”零售“16Byte大小的内存。每个零售商(kmem_cache)有两个“部门”,一个是“仓库”:kmem_cache_node,一个“营业厅”:kmem_cache_cpu。“营业厅”里只保留一个slab,只有在营业厅(kmem_cache_cpu)中没有空闲内存的情况下才会从仓库中换出其他的slab。所谓slab就是零售商(kmem_cache)批发的连续的整页内存,零售商把这些整页的内存分成许多小内存,然后分别“零售”出去,一个slab可能包含多个连续的内存页。slab的大小和零售商有关。
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
};
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链表表头 slab中没有空闲的object*/
#endif
};
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
};