SLUB 小对象分配机制与实现详解

SLUB 小对象分配机制与实现详解

源码路径rk3588/kernel-6.1/mm/slub.cslab_common.c
内核版本:Linux 6.1(RK3588,通常 CONFIG_SLUB=y
文档目录linuxDoc/mm/


目录


一、原理

1.1 为什么需要 slab

内核大量 固定大小小对象task_structinodesk_buff 头等),若每对象一次 __alloc_pages(0)

  • 浪费内存(页内碎片)
  • 增加 buddy 锁竞争

Slab 分配器页为 slab,在页内切分等长 object,按 cache 复用。

1.2 SLUB 设计思想

SLUB(Six Less Unfair Buddy)相对 SLAB/SLOB:

  • per-CPU slab 指针:热路径无中心锁
  • 合并 partial slab 管理:减少 per-node 链表遍历
  • freelist 在 object 内嵌指针:减少元数据

RK3588 defconfig 一般启用 CONFIG_SLUB,禁用 SLAB/SLOB。

1.3 三级存储层次

kmem_cache_alloc 热路径CPU slab + freelistpartial slab 链表 nodenew_slab → __alloc_pages

1.4 kmalloc

kmalloc(size, gfp) 根据 size 索引到预建 kmalloc-* cache(slab_common.ccreate_kmalloc_caches),本质仍是 kmem_cache_alloc


二、实现方式

2.1 核心对象

结构 说明
struct kmem_cache 对象大小、对齐、构造函数、flags
struct slab 一页或多页容器,freelistinusefrozen
struct kmem_cache_cpu per-CPU:slabfreelisttid
struct kmem_cache_node per-node partial/full 链表 + list_lock

2.2 分配入口

1
2
3
4
void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
{
return __kmem_cache_alloc_lru(s, NULL, gfpflags);
}

slab_alloc()slab_alloc_node()___slab_alloc()

2.3 快路径(inlined)

slub.cslab_alloc_node 内联路径:

  1. cpu_slab = slub_get_cpu_ptr(s->cpu_slab)
  2. c->slab 存在且 c->freelist 非空:直接从 freelist 弹对象get_freepointer
  3. 使用 tid 检测 CPU 迁移,不一致则走慢路径

2.4 慢路径:___slab_alloc

  1. get_partial():从 node partial 链表取 slab
  2. 若无:new_slab()allocate_slab()alloc_pages(order 由 oo/min_partial 决定)
  3. 新 slab 标记 frozen,填入 CPU slab
  4. debug 模式走 alloc_single_from_new_slab 与 red zone

2.5 释放:kmem_cache_free

  • 快路径:对象放回 CPU freelist
  • __slab_free:慢路径,可能将 slab 合并到 partial、或 discard_slab 归还 buddy
  • deactivate_slab:flush 当前 CPU slab 到 node 链表

2.6 slab_common.c 引导

函数 时机
create_boot_cache 极早期创建 task_struct 等 cache
kmem_cache_init 建立基本 cache
kmem_cache_init_late 完整 kmalloc cache 表
create_kmalloc_caches 按 size 分档

2.7 调试与硬化

CONFIG 目录/行为
SLUB_DEBUG redzone、poison
KASAN kasan/ 插桩
KFENCE kfence/ 采样检测
FAILSLAB failslab.c 故障注入

三、关键数据结构与接口

API 说明
kmem_cache_create 创建 cache
kmem_cache_alloc 分配对象
kmem_cache_free 释放对象
kmem_cache_alloc_node 指定 NUMA node
kmem_cache_alloc_bulk 批量分配
kmalloc / kfree 通用大小分配

锁顺序slub.c 文件头):slab_mutexnode->list_lockcpu_slab->lock


四、与页分配器关系

  • SLUB 不替代 buddy;slab 页来自 alloc_pages(gfp, order)
  • 若 buddy 失败,SLUB 返回 NULL,调用方处理;可能间接触发 OOM(见 08 文档)。
  • __GFP_COMP:folio/slub 大对象可能使用复合页。

五、调试与观测

手段 说明
/proc/slabinfo 各 cache 对象数、大小
/sys/kernel/slab/ sysfs 详情
slab_nomerge 启动参数 禁止合并 cache

附录:源码索引

主题 文件 约略行号
kmem_cache_alloc slub.c 3420
___slab_alloc slub.c 3100–3260
__slab_free slub.c 3459
kmem_cache_init slub.c 4818
kmalloc caches slab_common.c 869

文章互动

阅读 --

留言

0 条留言

正在加载留言…