内核管理页面使用了2个算法:伙伴算法和slub算法,伙伴算法以页为单位管理内存,但在大多数状况下,程序须要的并非一整页,而是几个、几十个字节的小内存。因而须要另一套系统来完成对小内存的管理,这就是slub系统。slub系统运行在伙伴系统之上,为内核提供小内存管理的功能。node
slub把内存分组管理,每一个组分别包含2^三、2^四、...2^11个字节,在4K页大小的默认状况下,另外还有两个特殊的组,分别是96B和192B,共11组。之因此这样分配是由于若是申请2^12B(4KB)大小的内存,就可使用伙伴系统提供的接口直接申请一个完整的页面便可。算法
slub就至关于零售商,它向伙伴系统“批发”内存,而后在零售出去。一下是整个slub系统的框图:数组
一切的一切源于kmalloc_caches[12]这个数组,该数组的定义以下:缓存
struct kmem_cache kmalloc_caches[PAGE_SHIFT] __cacheline_aligned;
每一个数组元素对应一种大小的内存,能够把一个kmem_cache结构体看作是一个特定大小内存的零售商,整个slub系统中共有12个这样的零售商,每一个“零售商”只“零售”特定大小的内存,例如:有的“零售商”只"零售"8Byte大小的内存,有的只”零售“16Byte大小的内存。数据结构
每一个零售商(kmem_cache)有两个“部门”,一个是“仓库”:kmem_cache_node,一个“营业厅”:kmem_cache_cpu。“营业厅”里只保留一个slab,只有在营业厅(kmem_cache_cpu)中没有空闲内存的状况下才会从仓库中换出其余的slab。
所谓slab就是零售商(kmem_cache)批发的连续的整页内存,零售商把这些整页的内存分红许多小内存,而后分别“零售”出去,一个slab可能包含多个连续的内存页。slab的大小和零售商有关。指针
相关数据结构:对象
物理页按照对象(object)大小组织成单向链表,对象大小是由objsize指定的。例如16字节的对象大小,每一个object就是16字节,每一个object包含指向下一个object的指针,该指针的位置是每一个object的起始地址+offset。每一个object示意图以下:接口
void*指向的是下一个空闲的object的首地址,这样object就连成了一个单链表。队列
向slub系统申请内存块(object)时:slub系统把内存块当成object看待。内存
向slub系统释放内存块(object)时,若是kmem_cache_cpu中缓存的slab就是该object所在的slab,则把该object放在空闲链表中便可,若是kmem_cache_cpu中缓存的slab不是该object所在的slab,而后把该object释放到该object所在的slab中。在释放object的时候能够分为一下三种状况:
以上是slub算法的主要原理。