标签:
http://blog.csdn.net/vanbreaker/article/details/7664296
1,为什么需要slab分配器:
利用伙伴系统进行分配内存只能按照页的单位进行分配,这样会造成很多的内存浪费,多了很多内存碎片,比如只需要申请10字节的,结果分配了一个页。
2,slab分配器和伙伴系统分配的差别
slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统。slab分配对象时,会使用最近释放的对象内存块,因此其驻留在CPU高速缓存的概率较高
Slab分配器由很多缓存(动态链表)组成,不同的缓存大小不同(如名为kmalloc-128的缓存所管理对象的长度为128字节)。Linux的Slab缓存分为专用和通用两种,通用缓存通过函数kmem_cache_init() 进行初始化,适用于特定对象,比如各种描述符,存放进程描述符的缓存大小就是sizeof(task_struct);而专用缓存则通过函数 kmem_cache_create()创建。通用Slab的对象大小预先定义好的,一般是2的次幂(cache对齐的需要),Linux使用13级, 如下:32、64、128、256、512、1024、2048、4096、8192、16384、32768、65536、131072。这样可以保证内存碎片小于百分之50
3,slab的概念
slab分配器把内存区看作对象(object),这些对象由一组数据结构和几个构造函数或者析构函数组成,分别用于初始化和回收内存。slab分配器把对象分组放进告诉缓存,包含高速缓存的主内存区被划分为多个slab,每个slab由一个或者多个连续的页组成,这些页框包含已分配对象和空闲对象。
每一个slab对象都有一个kmem_bufctl_t描述符,每个slab的对象描述符都存放在slab描述符的后面。因此((kmem_bufctl_t*)(slab + 1)就指向slab的kmem_bufctl_t描述符地址,语句((kmem_bufctl_t*)(slab + 1)[i]就是访问第i个对象的索引。
4,slab分配器用的相关数据结构
用于描述和管理cache的数据结构是struct kmem_cache
slab描述符可以放在以下两个地方
1,外部slab描述符,存在普通的高速缓存
2,内部slab描述符,位于分配给slab的第一个页框的起始位置
struct kmem_cache中定义了一个struct array_cache指针数组,数组的元素个数对应了系统的CPU数,和伙伴系统中的每CPU页框高速缓存类似,该结构用来描述每个CPU的本地高速缓存,在每个array_cache的末端都用一个指针数组记录了slab中的空闲对象,分配对象时,采用LIFO方式,也就是将该数组中的最后一个索引对应的对象分配出去,以保证该对象还驻留在高速缓存中的可能性。实际上,每次分配内存都是直接与本地CPU高速缓存进行交互,只有当其空闲内存不足时,才会从kmem_list中的slab中引入一部分对象到本地高速缓存中,而kmem_list中的空闲对象也不足了,那么就要从伙伴系统中引入新的页来建立新的slab了,这一点也和伙伴系统的
每CPU页框高速缓存很类似。
标签:
原文地址:http://www.cnblogs.com/zhiliao112/p/4251225.html