SLUB缓存管理

注:本文分析基于linux-4.18.0-193.14.2.el8_2内核版本,即CentOS 8.2

1、关于SLUB

目前大多数系统都不使用slab作为缓存的管理模式,转而使用slub,比如CentOS 7和8默认都是使用slub管理器。slub是基于slab的进一步优化改进,slub保留了slab的API接口函数,保证了对slab的兼容和无缝迁移。slub与slab的主要差异有以下几点,

  • 每CPU变量不再保存对象,而是保存slab缓冲区
  • 精简每node结点的三个链表,只保留部分空slab链表
  • 取消每node结点上所有CPU共享的空闲对象链表

2、SLUB管理结构kmem_cache

和slab一样,每个slab缓存由kmem_cache结构的一个实例表示,不过成员变量就不同了

struct kmem_cache {
	//每CPU slab缓存区,对应的是page粒度
	struct kmem_cache_cpu __percpu *cpu_slab;
	/* Used for retriving partial slabs etc */
	slab_flags_t flags; 
	unsigned long min_partial;//每个node结点的部分空slab缓冲区数量最小值
	unsigned int size;	//分配给对象的内存大小,包括下个空闲对象指针
	unsigned int object_size;//对象的实际大小
	unsigned int offset;	/* Free pointer offset. */
	//每CPU可用objects数量最大值
	unsigned int cpu_partial;
	...
	const char *name;	//slab缓存名称,比如ext4_inode_cache
	struct list_head list;	//slab双向链表指针,通过该变量链接到全局slab_caches链表
	...
	//每Node SLAB缓存对象
	struct kmem_cache_node *node[MAX_NUMNODES];
};

我们主要来看下每CPU slab缓存和每node slab缓存,这也是和slab的主要差别之处。

3、每CPU slab缓存kmem_cache_cpu

struct kmem_cache_cpu {
	void **freelist;	//指向下个空闲对象
	unsigned long tid;	/* Globally unique transaction id */
	struct page *page;	//该CPU正在使用的slab缓冲区描述符,freelist指向此slab的下一个空闲对象
	struct page *partial;	//该CPU的部分空slab链表,该链表中的slab会被冻结
};

成员很简单,需要说明的是struct page *page,这个指向的是CPU正在使用的slab缓冲区,为什么page指向的是slab描述符呢?别忘记,struct page是个联合体,可作为slab缓存描述符。相比于slab,其每cpu保存的是空闲对象,是slab缓冲区的子集。

4、缓冲区描述符struct page

struct page {
	unsigned long flags;		/* Atomic flags, some possibly updated asynchronously */

	struct {	/* slab, slob and slub */
		struct list_head slab_list; //通过该变量链接slab描述符到部分空或者完全用尽slab管理链表

		struct kmem_cache *slab_cache; //指向该slab描述符所属的slab管理结构
		/* Double-word boundary */
		void *freelist;		/* first free object */
		union {
			unsigned long counters;		/* SLUB */
			struct {			/* SLUB */
				unsigned inuse:16;	//该slab缓冲区中正在使用的对象数量
				unsigned objects:15; //该slab缓冲区包含的对象数量
				unsigned frozen:1;	//slab缓冲区冻结状态
			};
		};
	};
	...
};

上面有说过,struct page是个联合体,我们把针对slub的成员变量择出来看,比较清晰。

5、kmem_cache_node

最后是每node变量,相比于slab的三个slab管理链表,slub只有部分空链表,而完全用尽链表只有在打开slub debug开关时才会存在。

struct kmem_cache_node {
	spinlock_t list_lock;

	unsigned long nr_partial;
	struct list_head partial; //该node的部分空slab链表
	//开启CONFIG_SLUB_DEBUG才有完全用尽slab链表,主要用于调试
	atomic_long_t nr_slabs;
	atomic_long_t total_objects;
	struct list_head full; //完全用尽slab链表
};

6、结构关系

这么多结构,还是通过图来说明比较清晰明了。

  • 所有的slab缓存都挂载在slab_caches全局链表上,这也就是我们在/proc/slabinfo中看到的所有slab缓存
  • 每个slab缓存对应一个kmem_cache结构
  • kmem_cache结构中有一个每CPU变量kmem_cache_cpu结构,用来作为本地CPU的高速缓存,存放的是slab缓冲区
  • 每CPU变量kmem_cache_cpu结构中的freelist指向下个可用的slab对象
  • kmem_cache结构中还有一个每Node的kmem_cache_node结构,用来作为NUMA结构中Node的缓存
  • kmem_cache_node结构中包含两个slab链表,partial、full(在slub debug开关开启时),存放的是slab缓冲区
  • slab缓冲区使用页描述符呈现,每个slab缓冲区中会包含多个对象
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值