大四一段时间曾经学习过 Linux 内核的一小部分,自然读过大名鼎鼎的 slab 内存管理;后来又看了看<Modern C++ Design>中的 Small Object Allocator, 觉得它们在原理上大致相同。这里仅将其基本原理简单介绍一下,以飨读者。
1. 先说 slab
Linux 的 slab 内存管理由两个部分组成,一是所谓的 cache, 再就是 slab;每一种数据结构对应一个 cache,举例来说,struct task_struct (这个结构非常大,就是所谓的进程控制块)对应 taskstruct_cachep, 而这种数据结构在分配内存时就只能从对应的 cache 中分配,也即,要分配一个 struct task_struct, 就只能
kmem_cache_alloc(taskstruct_cachep);总体上,这个 cache 管理着一个对象(object)池,分配内存时,直接从池中取空闲的对象,而释放时则返还给这个对象池,只有在池为空时才向系统申请内存页;所以这个对象池是非常快的。
这个内存池由一个cache管理,由多个 slab 组成,每个 slab 可以缓存多个对象。注意,slab是固定大小的而且都是一个页的大小(4K), 这是为了计算的方便,后面就会看到。cache 和 slab 的结构如图所示:
_________ _________
cachep----->| slab |------>| slab |---->......
| | | |
| | | |
| object | | object |
| object | | object |
(4K) |___ _____| (4K)|________|
一个 slab 又由两部分组成,这个4K的内存块的前面的一小部分是 slab 控制块(Linux 里面稍有不同),紧接着就是一组 object。slab控制块维护着一个指针,指向当前空闲着的对象。当一个对象被释放时,就让这个指针指向这个刚释放的对象;而在申请内
1. 先说 slab
Linux 的 slab 内存管理由两个部分组成,一是所谓的 cache, 再就是 slab;每一种数据结构对应一个 cache,举例来说,struct task_struct (这个结构非常大,就是所谓的进程控制块)对应 taskstruct_cachep, 而这种数据结构在分配内存时就只能从对应的 cache 中分配,也即,要分配一个 struct task_struct, 就只能
kmem_cache_alloc(taskstruct_cachep);总体上,这个 cache 管理着一个对象(object)池,分配内存时,直接从池中取空闲的对象,而释放时则返还给这个对象池,只有在池为空时才向系统申请内存页;所以这个对象池是非常快的。
这个内存池由一个cache管理,由多个 slab 组成,每个 slab 可以缓存多个对象。注意,slab是固定大小的而且都是一个页的大小(4K), 这是为了计算的方便,后面就会看到。cache 和 slab 的结构如图所示:
_________ _________
cachep----->| slab |------>| slab |---->......
| | | |
| | | |
| object | | object |
| object | | object |
(4K) |___ _____| (4K)|________|
一个 slab 又由两部分组成,这个4K的内存块的前面的一小部分是 slab 控制块(Linux 里面稍有不同),紧接着就是一组 object。slab控制块维护着一个指针,指向当前空闲着的对象。当一个对象被释放时,就让这个指针指向这个刚释放的对象;而在申请内