根据是否打开Slub Debug,next object指针可以有两种方式放置,如果打开了Slub Debug,则采用指针外置式;反之,采用指针内置式 。两种指针放置方式如下图:
- 指针外置式

文章插图
- 指针内置式

文章插图
指针内置式的方法实际上是复用了object的前8个字节,因为在object被分配出去之前,这一段内存具体存放什么内容并不重要,所以可以利用这一段内存来保存下一个free object的地址 。
- kmem_cache_cpu
struct kmem_cache_cpu {/* 指向下一个空闲的object,用于快速找到可用对象 */void **freelist;/* Pointer to next available object *//** 要保证tid和kmem_cache是由同一个CPU访问 。* 开启了内核抢占后,访问tid和kmem_cache的CPU可能不是同一个CPU,* 所以要检查是否匹配,直到它们是由同一个CPU进行访问*/unsigned long tid;/* Globally unique transaction id *//* 指向当前使用的slab */struct page *page;/* The slab from which we are allocating *//* 指向当前cpu上缓存的部分空闲slab链表 */struct page *partial;/* Partially allocated frozen slabs */#ifdef CONFIG_SLUB_STATS/** 记录对slab操作的状态变化,这个stat非常重要,* 通过这个stat就大概了解object从申请到释放经过了哪些步骤*/unsigned stat[NR_SLUB_STAT_ITEMS]; #endif};- kmem_cache_node
struct kmem_cache_node {spinlock_t list_lock;/* 此处省略掉SLAB的配置 */#ifdef CONFIG_SLUB/* 挂入kmem_cache_node中的slab数量 */unsigned long nr_partial;/* 指向当前内存节点上的部分空闲slab链表 */struct list_head partial;#ifdef CONFIG_SLUB_DEBUGatomic_long_t nr_slabs;atomic_long_t total_objects;struct list_head full;#endif#endif};page中描述Slub信息的字段:struct page {/* 如果flag设置成PG_slab,表示页属于slub分配器 */unsigned long flags;union {struct address_space *mApping;/* 指向当前slab中第一个object */void *s_mem;/* slab first object */atomic_t compound_mapcount;/* first tail page */};union {pgoff_t index;/* Our offset within mapping. *//* 指向当前slab中第一个空闲的object */void *freelist;/* sl[aou]b first free object */};union {unsigned counters;struct {union {atomic_t _mapcount;unsigned int active;/* SLAB */struct {/* SLUB *//* 该slab中已经分配使用的object数量 */unsigned inuse:16;/* 该slab中的所有object数量 */unsigned objects:15;/** 如果slab在kmem_cache_cpu中,表示处于冻结状态;* 如果slab在kmem_cache_node的部分空闲slab链表中,表示处于解冻状态*/unsigned frozen:1;};int units;/* SLOB */};atomic_t _refcount;};};union {/* 作为链表节点加入到kmem_cache_node的部分空闲slab链表中struct list_head lru;/* Pageout list*/struct dev_pagemap *pgmap;struct {/* slub per cpu partial pages */struct page *next;/* Next partial slab */int pages;/* Nr of partial slabs left */int pobjects;/* Approximate # of objects */};struct rcu_head rcu_head;struct {unsigned long compound_head; /* If bit zero is set */unsigned int compound_dtor;unsigned int compound_order;};};union {unsigned long private;struct kmem_cache *slab_cache;/* SL[AU]B: Pointer to slab */};......}Slub的分配过程Slub的分配流程大致如下:首先从kmem_cache_cpu中分配,如果没有则从kmem_cache_cpu的partial链表分配,如果还没有则从kmem_cache_node中分配,如果kmem_cache_node中也没有,则需要向伙伴系统申请内存 。
文章插图
Slub的分配接口是kmem_cache_malloc() 。其分配object的流程大概如下:首先在kmem_cache_cpu所使用的slab中查找free object,如果当前slab中有free object,则返回这个object 。如果当前slab没有free object,就要看Slub是否开启了kmem_cache_cpu的Partial队列,如果开启了partial队列,就在Partial队列中查看有没有free object的slab,如果有的话就选定这个slab,并返回其free object 。如果kmem_cache_cpu的partial链表中也没有拥有free object的slab,则在kmem_cache_node中查找 。如果kmem_cache_node中的slab有free object,则选定这个slab并返回free object 。如果kmem_cache_node中也没有free object,则需要向伙伴系统申请内存,制作新的slab 。
创建slab缓存(kmem_cache)的函数分析斗胆分析一下slab缓存的创建过程,新手小白分析内核代码,分析的可能不够深度和完整,如有不对还请各路高手指教,提前谢过 。
函数调用流程:
kmem_cache_create()——> kmem_cache_create_usercopy()——> create_cache()——> __kmem_cache_create()——> kmem_cache_open()
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字节跳动宣布开源 KubeWharf,一个实践驱动的云原生项目集
- 机器人避障中的超声波传感器
- 改善Java代码的八个建议
- 制作红、蓝底色的证件照,学会Word三步搞定,告别PS软件
- 用break模拟python的while循环,验证go语言for循环关键机制
- Apache OpenOffice 4.1.13发布 - 是的,它还在更新
- 网络工程师的Python之路——Netmiko终极指南
- 一种千万级用户实时统计用户数的简单实现
- 扩展你的KUBECTL功能
- 汤姆索亚历险记的故事内容及故事情节 汤姆索亚历险记故事梗概是什么
