Read the fucking source code!A picture is worth a thousand words.
说明:
- Kernel版本:4.14
- ARM64处理器,Contex-A53,双核
- 使用工具:Source Insight 3.5, Visio
slab, slub, slobslabslub/slobslobslubslub
先来一个初印象:
有四个关键的数据结构:
struct kmem_cacheSLAB缓存
/*
* Slab cache management.
*/
struct kmem_cache {
struct kmem_cache_cpu __percpu *cpu_slab; //每个CPU slab页面
/* Used for retriving partial slabs etc */
unsigned long flags;
unsigned long min_partial;
int size; /* The size of an object including meta data */
int object_size; /* The size of an object without meta data */
int offset; /* Free pointer offset. */
#ifdef CONFIG_SLUB_CPU_PARTIAL
/* Number of per cpu partial objects to keep around */
unsigned int cpu_partial;
#endif
struct kmem_cache_order_objects oo; //该结构体会描述申请页面的order值,以及object的个数
/* Allocation and freeing of slabs */
struct kmem_cache_order_objects max;
struct kmem_cache_order_objects min;
gfp_t allocflags; /* gfp flags to use on each alloc */
int refcount; /* Refcount for slab cache destroy */
void (*ctor)(void *); // 对象构造函数
int inuse; /* Offset to metadata */
int align; /* Alignment */
int reserved; /* Reserved bytes at the end of slabs */
int red_left_pad; /* Left redzone padding size */
const char *name; /* Name (only for display!) */
struct list_head list; /* List of slab caches */ //kmem_cache最终会链接在一个全局链表中
struct kmem_cache_node *node[MAX_NUMNODES]; //Node管理slab页面
};
struct kmem_cache_cpuslab页面
struct kmem_cache_cpu {
void **freelist; /* Pointer to next available object */ //指向空闲对象的指针
unsigned long tid; /* Globally unique transaction id */
struct page *page; /* The slab from which we are allocating */ //slab缓存页面
#ifdef CONFIG_SLUB_CPU_PARTIAL
struct page *partial; /* Partially allocated frozen slabs */
#endif
#ifdef CONFIG_SLUB_STATS
unsigned stat[NR_SLUB_STAT_ITEMS];
#endif
};
struct kmem_cache_nodeslab页面slab
/*
* The slab lists for all objects.
*/
struct kmem_cache_node {
spinlock_t list_lock;
#ifdef CONFIG_SLUB
unsigned long nr_partial; //slab页表数量
struct list_head partial; //slab页面链表
#ifdef CONFIG_SLUB_DEBUG
atomic_long_t nr_slabs;
atomic_long_t total_objects;
struct list_head full;
#endif
#endif
};
struct pageslab页面struct pageunionstruct pageslub
struct page {
union {
...
void *s_mem; /* slab first object */
...
};
/* Second double word */
union {
...
void *freelist; /* sl[aou]b first free object */
...
};
union {
...
struct {
union {
...
struct { /* SLUB */
unsigned inuse:16;
unsigned objects:15;
unsigned frozen:1;
};
...
};
...
};
};
/*
* Third double word block
*/
union {
...
struct { /* slub per cpu partial pages */
struct page *next; /* Next partial slab */
#ifdef CONFIG_64BIT
int pages; /* Nr of partial slabs left */
int pobjects; /* Approximate # of objects */
#else
short int pages;
short int pobjects;
#endif
};
struct rcu_head rcu_head; /* Used by SLAB
* when destroying via RCU
*/
};
...
struct kmem_cache *slab_cache; /* SL[AU]B: Pointer to slab */
...
}
图来了:
针对Slub的使用,可以从三个维度来分析:
- slub缓存创建
- slub对象分配
- slub对象释放
下边将进一步分析。
3.1 kmem_cache_create
kmem_cache_createslab缓存
先看一下这个接口的函数调用关系图:
kmem_cache_createslab缓存kmem_cachekmem_cachekmem_cache_cpukmem_cache_nodeslab缓存slab缓存slab缓存calculate_sizesforce_orderkmem_cachesize/min/ookmem_cache_order_objectsorder对象数量slab缓存kmem_cacheslab缓存kmem_cacheslab缓存kmem_cache_initkmem_cachekmem_cache_nodekmem_cache_initslab缓存kmem_cachekmem_cache_nodekmem_cache_cpu__alloc_percpuslab缓存
3.2 kmem_cache_alloc
kmem_cache_alloc
看一下大体的调用流程图:
Buddy Systemper-CPU缓存
per-CPU缓存per-CPU缓存Nodeslab页per-CPU缓存NodeBuddy Systemper-CPU缓存
还是用图来说明更清晰,分为以下几步来分配:
fastpathslowpath-1slowpath-2slowpath-2slowpath-3slowpath-3kmem_cache.cpu_partialslab页slowpath-4slowpath-4Buddy System
3.2 kmem_cache_free
kmem_cache_freekmem_cache_allockmem_cache_alloc
调用流程图如下:
效果如下:
put_cpu_partialput_cpu_partialunfreeze_partials
nr_partial/min_partial