-
Slub 简介
Linux 内核内存管理用了两个算法:伙伴算法(以页为单位的大内存)和 slub 算法(以字节为单位的小内存),其中 slub 系统运行在伙伴系统之上。
slub 进行内存分组管理,分别设置 2^3 ~ 2^11 字节和 96B、192B 共 11 个组,
在内核中的控制结构为 kmalloc_caches[12],
struct kmem_cache kmalloc_caches[PAGE_SHIFT] __cacheline_aligned;
每个数组元素(kmem_cache)对应一种大小的内存,kmem_cache 的主要结构有 kmem_cache_cpu 和 kmem_cache_cpu。在 kmem_cache_cpu 中只存一个 slab(连续的整页内存),只有在 kmem_cache_cpu 中没有空闲内存的情况下才会从 kmem_cache_node 中换出其它的 slab。
+ ### 申请结构
物理页按照 object 大小组成链表,每个 object 包含指向下一个 object 的指针(void*),当 slub 系统申请内存块的时候,会把内存块当 object 看待。
![image-20220909141219828](/i/l/?n=23&i=blog/2723796/202212/2723796-20221229123323568-1721897178.png)
+ ### 申请内存
##### case1: slub 系统初始化,也就是第一次申请
当前 kmem_cache_cpu 和 kmem_cache_node 中没有可用的 slab,因此只能向伙伴系统申请空闲内存页,并将其分为多个 object,然后取出其中的一个 object 并标记为已被占用,接着返回给用户。
其余的 object 会标记为空闲并放在 kmem_cache_cpu 中保存,kmem_cache_cpu 中的 freelist 保存着下一个空闲 object 的地址。
![image-20220909142543215](/i/l/?n=23&i=blog/2723796/202212/2723796-20221229123322787-1644051019.png)
##### case2: kmem_cache_cpu 中保存的 slab 上有空闲的 object 可用
直接把 kmem_cache_cpu 中的下一个空闲 object 返回给用户,并把 freelist 指向下一个空闲的 object。
![image-20220909142554470](/i/l/?n=23&i=blog/2723796/202212/2723796-20221229123321811-1261272047.png)
##### case3: kmem_cache_cpu 中没用空闲但 kmem_cache_node 中有空闲
此时会从 kmem_cache_node 的 partial 变量中获取有空闲的 object 的 slab 并返回给用户。
同时还会对 kmem_cache 进行一些调整,其中 kmem_cache_node 中的 full 和 partial 分别存放了全满和不满的 slab。这时会从 partial 中挑一个不满的 slab 放到 kmem_cache_cpu 中,并把 kmem_cache_node 中满了的 slab 放到 full 中。
![image-20220909142641448](/i/l/?n=23&i=blog/2723796/202212/2723796-20221229123320184-1994672078.png)
##### case4: kmem_cache_node 和 kmem_cache_cpu 中的 slab 已经都满了
这时只能向伙伴系统重新申请一个 slab。
![image-20220909143332666](/i/l/?n=23&i=blog/2723796/202212/2723796-20221229123317756-1254829783.png)
+ ### 释放内存
##### case1: kmem_cache_cpu 中缓存的 slab 就是该 object 所在的 slab
该 slab 还在 kmem_cache_cpu 中,把该 object 放到空闲列表中即可。
下面的情况都是该 slab 已经被放到了 kmem_cache_node 中。
##### case2: object 所在的 slab 是 full 状态
那么释放 object 之后,该 slab 就是 partail 状态,此时把该 slab 添加到 kmem_cache_node 中的 partial 链表中。
![image-20220909144333503](/i/l/?n=23&i=blog/2723796/202212/2723796-20221229123315903-830212992.png)
##### case3:slab 是 partial 状态
直接把该 object 加入到该 slab 的空闲队列中
![image-20220909144915473](/i/l/?n=23&i=blog/2723796/202212/2723796-20221229123314064-139085667.png)
##### case4: object 在释放后,slab 中的 object 全部是空闲的
此时还需要把整个 slab 释放掉。
![image-20220909145042163](/i/l/?n=23&i=blog/2723796/202212/2723796-20221229123310794-2131286650.png)
+ #### 参考文献
+ https://blog.csdn.net/lukuen/article/details/6935068
标签:object,2723796,kmem,cache,内存,Linux,slub,slab,cpu
From: https://www.cnblogs.com/m00nflower/p/17012231.html