1. Slab分配器概述
Slab分配器是Linux内核中用于高效管理内核对象内存分配的核心机制。我第一次接触Slab是在调试一个内核模块的内存泄漏问题时,发现常规的kmalloc()/kfree()无法满足频繁创建销毁相同类型对象的需求。Slab通过预分配和缓存策略,显著减少了内存碎片和分配开销。
Slab的核心思想其实很像现实生活中的"物件回收站":当我们频繁使用某种固定大小的对象时,与其每次都新建再销毁,不如把用完的对象放在一个专门区域,下次需要时直接取用。这种思路在内核中尤为重要,因为像task_struct、inode等关键数据结构会被频繁创建和释放。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Slab初始化过程解析
2.1 初始化时机与入口
Slab的初始化发生在内核启动的早期阶段,具体在start_kernel() -> mm_init() -> kmem_cache_init()中。这个时机选择很有讲究 - 必须在内存管理系统基本就绪后,但在其他子系统开始大量创建对象之前完成初始化。
c复制// mm/slab.c
void __init kmem_cache_init(void)
{
// 初始化阶段划分
enum {
DOWN, // 准备阶段
PARTIAL, // 部分初始化
PARTIAL_NODE,
UP, // 运行阶段
FULL // 完全初始化
} stage = DOWN;
// 分阶段初始化
while (stage != FULL) {
switch (stage) {
case DOWN:
create_boot_cache(kmem_cache, "kmem_cache",
sizeof(struct kmem_cache), 0);
stage = PARTIAL;
break;
// 其他阶段处理...
}
}
}
2.2 关键数据结构初始化
Slab的核心是kmem_cache结构体,它相当于特定类型对象的"模具"。初始化时会先创建kmem_cache的cache(是的,这是个自举问题),然后逐步建立其他关键cache:
- 首先创建kmem_cache的cache(用于分配后续的kmem_cache实例)
- 然后创建kmem_cache_node的cache
- 最后创建各种常规对象的cache(如task_struct等)
注意:这个自举过程非常精妙 - 必须先有kmem_cache才能分配kmem_cache,所以最初的几个cache是通过特殊方式手动构建的。
2.3 缓存着色机制
Slab初始化时有个容易被忽视但很重要的细节 - 缓存着色(cache coloring)。这是为了解决硬件缓存冲突问题而设计的:
c复制// mm/slab.c
static size_t calculate_slab_order(struct kmem_cache *cachep,
size_t size, size_t align, unsigned long flags)
