背景
Read the fucking source code!A picture is worth a thousand words.

说明:

  1. Kernel版本:4.14
  2. ARM64处理器,Contex-A53,双核
  3. 使用工具:Source Insight 3.5, Visio
1. 概述
slab, slub, slobslabslub/slobslobslubslub

先来一个初印象:

2. 数据结构

有四个关键的数据结构:

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 */    
    ...
}

图来了:

3. 流程分析

针对Slub的使用,可以从三个维度来分析:

  1. slub缓存创建
  2. slub对象分配
  3. 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