Linux Kernel/SLUB 对象分配器

从当前 CPU 的空闲链表快速分配内核对象

Linux SLUB 将同类对象组织在 slab 中,并用 per-CPU freelist 满足常见分配,避免每次都访问集中管理的部分空闲 slab 列表。

v6.12内存管理核验 2026-10-09
相关概念

工程问题#

内核频繁分配与释放固定规格的小对象;若每次都进入共享分配结构,多 CPU 会争用管理状态。

实际实现#

__slab_alloc_node 读取当前 CPU 的 freelist、slab 和事务标识 tid。快路径适用且对象、NUMA 节点等条件满足时,从链表取对象,并将 freelist 与下一 tid 一起进行本 CPU 比较交换;更新失败便重试,不满足条件则进入慢路径。

处理流程#

  1. 读取当前 CPU 的事务标识、空闲对象头和 slab
  2. 检查快路径开关、可用对象及目标 NUMA 节点
  3. 比较交换 freelist 与 tid,成功则返回对象,冲突则重试
  4. 缺少可用对象或快路径不适用时进入补充或分配 slab 的慢路径

源码片段#

固定版本 · 原文摘录
mm/slub.cv6.12 · L3557–L3567
查看原文件
3557static inline bool3558__update_cpu_freelist_fast(struct kmem_cache *s,3559			   void *freelist_old, void *freelist_new,3560			   unsigned long tid)3561{3562	freelist_aba_t old = { .freelist = freelist_old, .counter = tid };3563	freelist_aba_t new = { .freelist = freelist_new, .counter = next_tid(tid) };35643565	return this_cpu_try_cmpxchg_freelist(s->cpu_slab->freelist_tid.full,3566					     &old.full, new.full);3567}
__update_cpu_freelist_fast

把旧 freelist 与旧 tid 作为一个待比较状态,把新 freelist 与递增后的 tid 作为新状态;本 CPU 比较交换同时验证并更新二者。

mm/slub.cv6.12 · L3956–L3964
查看原文件
3956	object = c->freelist;3957	slab = c->slab;39583959	if (!USE_LOCKLESS_FAST_PATH() ||3960	    unlikely(!object || !slab || !node_match(slab, node))) {3961		object = __slab_alloc(s, gfpflags, node, addr, c, orig_size);3962	} else {3963		void *next_object = get_freepointer_safe(s, object);3964
__slab_alloc_node · 快慢路径分流

快路径未启用、freelist 为空、没有当前 slab 或节点不匹配时进入 __slab_alloc。只有通过检查才准备取出下一个空闲对象;后续原子更新失败会回到 redo 重试。

片段分别展示联合状态更新和快慢路径条件。完整重试逻辑位于 __slab_alloc_node,不能把 helper 当成独立可复用的通用无锁栈。

收益与取舍#

工程分析

带来的收益

  • 常见分配使用 per-CPU 状态,减少对集中 partial 列表锁的访问
  • 事务标识与链表头联合验证,检测被抢占、迁移或期间发生的本 CPU 状态变化

付出的代价

  • per-CPU 缓存与部分填充 slab 可能保留空闲内存,需权衡局部性与内存占用
  • 重试、慢路径、NUMA 和调试钩子都会改变成本;不能宣称所有分配恒定时间或无锁
  • 这段比较交换只保护对应本 CPU 操作,并非任意跨 CPU 链表访问协议

可比较的选择

集中空闲对象链表管理状态较集中,但多 CPU 操作需要更多共享同步。

伙伴页分配器解决按页、按阶的连续块分配;SLUB 位于其上层处理小对象,二者并非直接替换关系。

版本与适用范围#

Linux v6.12,非 CONFIG_SLUB_TINY 的对象分配路径。PREEMPT_RT 不使用该无锁快路径;源码中的慢路径、调试配置与平台原子原语需要一并阅读。

参考来源#

源码、官方文档与原始论文
01
linux · __slab_alloc_node

mm/slub.c · __slab_alloc_node

源码v6.12
02
linux · __update_cpu_freelist_fast

mm/slub.c · __update_cpu_freelist_fast

源码v6.12
03
linux · SLUB locking / USE_LOCKLESS_FAST_PATH

mm/slub.c · SLUB locking / USE_LOCKLESS_FAST_PATH

源码v6.12

相关实现与比较#

4 个相关案例
14 个匹配案例