多图详解Linux内存分配器Slub
原创
Linux内存分配器Slub详解
Linux内核中的内存分配器是内核管理内存的重要组件。Slub(Slab分配器)是Linux内核中一个常用的内存分配器,它重点用于分配频繁分配和释放的小对象。本文将详细介绍Slub内存分配器的原理、工作流程以及优缺点。
1. Slub内存分配器的原理
Slub内存分配器基于Slab机制,其重点思想是将多个小对象预先分配到一个更大的内存块中,形成一个对象池。当需要分配小对象时,可以直接从这个对象池中取出,而不需要每次都进行内存的分配和释放操作。
2. Slub内存分配器的工作流程
Slub内存分配器的工作流程大致可以分为以下几个步骤:
- 初始化:在系统启动时,Slub分配器会初始化一系列的Slab对象,这些对象将用于存放小对象。
- 分配:当需要分配小对象时,Slub分配器会从相应的Slab对象中取出一个空闲对象,分配给用户。
- 释放:当小对象不再需要时,Slub分配器会将它放回对应的Slab对象中,以供后续再次分配。
- 回收:当Slab对象中的对象数量大致有一定阈值时,Slub分配器会进行回收操作,将Slab对象中的所有对象全部释放,以便进行后续的内存复用。
3. Slab对象的结构
Slub内存分配器中的Slab对象结构如下:
struct kmem_cache {
unsigned long flags; // 标志
unsigned long size; // Slab对象大小
unsigned long offset; // 对象偏移量
unsigned long color; // 颜色
struct page *page; // 指向page结构的指针
struct kmem_cache_cpu *cpu_slab; // 处理器相关的Slab信息
unsigned long objects; // 对象数量
unsigned long free; // 空闲对象数量
struct kmem_cache *slabp; // 指向父Slab对象的指针
struct kmem_cache *full; // 指向满Slab对象的指针
void (*ctor)(void *, void *); // 构造函数
void (*dtor)(void *, void *); // 析构函数
void (*ctor_top)(void *, void *); // 构造函数(顶部)
void (*dtor_top)(void *, void *); // 析构函数(顶部)
unsigned int inuse; // 已使用对象数量
unsigned int align; // 对齐方案
unsigned int reserved; // 保留位
void *cpu_partial; // 处理器相关的部分对象信息
struct page *partial; // 部分对象信息
spinlock_t lock; // 锁
unsigned int objects_per_slab; // 每个Slab中的对象数量
unsigned int free_slabs; // 空闲Slab数量
struct list_head list; // 链表节点
};
4. Slub内存分配器的优缺点
优点:
- 降低了内存碎片:由于Slub分配器预先分配了一块连续的内存空间,故而可以降低内存碎片。
- 尽也许降低损耗了分配和释放快速:Slub分配器通过对象池的方案,可以迅捷地分配和释放小对象,尽也许降低损耗了内存分配的快速。
- 降低了内存访问次数:由于Slub分配器中的对象都是连续的,故而可以降低内存访问次数,尽也许降低损耗内存访问速度。
缺点:
- 内存占用较大:由于Slub分配器需要为每个对象分配额外的元数据,故而相比其他内存分配器,其内存占用会更大。
- 不拥护动态调整:Slub分配器不拥护动态调整Slab对象的大小,这也许会约束其在某些场景下的使用。