基础知识介绍

一个slab由一个或者多个连续的物理页组成。

一个缓存由1个或者多个slab组成。

semaphores
semaphores

slab、缓存、对象之间的关系如图所示:


slab分配算法使用缓存来保存内核对象。

当创建一个缓存时,该缓存会分配有多个初始标记位空闲的对象。
一个缓存里的对象的数量跟关联的slab的大小有关。比如一个12KB的slab可存储6个2KB大小的对象。

最初,在一个缓存里的所有对象都标记为空闲。
当需要一个内核数据结构的对象时,分配器可从缓存中分配任一个空闲对象来满足该请求。从缓存中分配的对象被标记为已使用。

struct task_structtask_struct

slab分配算法

在Linux上,一个slab可能有3种状态:

  1. 全满
    该slab上的所有对象是已使用的;
  2. 全空
    该slab上的所有对象都是空闲的;
  3. 部分空
    该slab上的对象有空闲的,也有已使用的;

首先,slab分配器会尝试用部分空的slab上的空闲对象来满足请求。
其次,如果所有部分空的slab上的所有空闲对象都不满足请求,则slab分配器会尝试用全空的slab上的空闲对象来满足请求。
最后,如果所有全空的slab上的空闲对象都不满足请求,则需要从连续的物理页上分配一个新的slab,并将该slab分配给相应缓存,然后从该slab上分配该对象的缓存来满足请求。

slab分配器的两个主要的优点:

  1. 不会因为碎片而导致内存浪费
    没有碎片问题,因为每个唯一的内核数据结构都有一个关联度的缓存,每个缓存都是由多个slab组成,每个slab都根据要表示对象的大小划分。因此,当内核发出对象内存分配请求时,slab分配器返回的就是需要表示的对象大小的精确内存。
  2. 内存请求可快速得到满足
    当内核频繁地分配和释放对象时,使用slab分配器来管理内存就及其有效。虽然分配内存和释放内存是一个耗时的过程,但是由于对象都是提前创建好的,所以可快速地从缓存中分配。而且,当内核用完了一个对象并要释放该对象时,内核就标记该对象为空闲,将该对象返还给该对象的缓存,从而使其可立即用于后续来自内核的内存请求。

比较slub分配器和slab分配器

pageper-CPU