slab分配器
功能:提供小的内存块,也可用作一个缓存。
分配和释放内存在内核代码上很常见。为了使频繁分配和释放内存所导致的开销尽量变小,程序员通常使用空闲链表。当分配的内在块不再需要时,将这块内存插入到空闲链表中,而不是真正的释放掉,这种空闲链表相当于内存块缓冲区。但这种方法的不足之处是,内核没有一种手段能够全局地控制空闲链表的大小,实时地更新这些空闲链表的大小。事实上,内核根本也不可能知道有多少空闲链表存在。
-
为了解决上述问题,内核心提供了slab层或slab分配器。它作为一个通用的内核数据结构缓冲层。slab层使用了以下几个基本原理:
-
经常使用的数据结构一般来说会被经常分配或释放,所以应该缓存它们。
-
频繁地分配和释放内存会导致内在碎片(不能找到合适的大块连续的物理地址空间)。为了防止这种问题,缓冲后的空闲链表被存放到连续的物理地址空间上。由于被释放的数据结构返回到了空闲链表,所以没有导致碎片。
-
在频繁地分配和释放内存空间在情况下,空闲链表保证了更好的性能。因为被释放的对象空间可立即用于下次的分配中。
-
如果分配器能够知道诸如对象大小、页大小和总的缓冲大小时,它可以作出更聪明的决定。
-
如果部分缓冲区对每-CPU变量,那么,分配和释放操作可以不需要SMP锁。
-
如果分配器是非一致内存,它能从相同的内存结点中完成分配操作。
-
存储的对象可以被着色,以防止多个对象映射到同一个缓冲。
Linux中的slab层就是基于上述前提而实现的。
slab层将不同的对象进行分组,称之为“缓冲区(cache)”。一个缓冲区存储一种类型的对象。每种类型的对象有一个缓冲区。kmalloc()的实现就是基于slab层之上的,使用了一族通用的缓冲区。这些缓冲区被分成了一些slab。这些slab是由一个或多个物理上连续的页组成的。每个缓冲区可包含多个slab。
每个slab包含有一些数量的对象,也即被缓冲的数据结构。每个slab问量处于三种状态之间:满、部分满、空。当内核请求一个新的对象时,它总是先查看处于部分满状态的slab,查看是否有合适的空间,如果没有,则空的slab中分配空间。