slab字面意思是被分割的厚板/石板,类似与buddy算法的含义(页可以按照2的次幂组织成一个元素,也可以分离,就像小伙伴一样,buddy算法因“时聚时散”这个表现而得名);slab的含义就是把大块的空间,分解为小块的空间。slab具体的特性是它包含不同的对象,就像书架一样,同一类型的对象就放在什么同一类型的slab(书架)里,因为一个slab可能装不下所有的对象,所以有些对象类型会有多个slab。slab并不是一开始就有的算法,它的出现是为了优化buddy算法,buddy算法以页(4096字节)为单位,进行管理,即使很小的数据修改,也会动用4096字节,花销大,而且数据这一块,那一块,不好管理。
所以,buddy系统就像一个大的书架,slab就像书架的格子一样。书架用于管理一个专业领域的书,如C语言/C++/JAVA/C#,而格子用于管理一个小类,C语言放在一个slab,C++放入一个slab....。而组成slab的“对象”就是具体的书本,如《C专家编程》,《C语言陷阱》等就是C语言这个slab 的对象。
因为内存初始化的时间比分配和释放时间长好多,slab增加一个类似对象池的特性,slab会缓存已经被“释放”的对象,以便下次重用,不必再初始化。对象用该高速缓存结构kmem_cache描述。通过kmem_cache_create创建。虽然名为高速缓存,但是它不是硬件上的高速缓存,它只是主存上的区域,但是和硬件上的高速缓存高度相关。
注意内核分配内存的函数kmalloc使用了__do_kmalloc,这个函数先按照size,找到一个kmem_cache,然后从kmem_cache中分配内存对象。这说明,kmalloc是通过高速缓存的大小来构建一个通用内存分配器的。用cat /proc/slabinfo命令可以查看到kmem_cache的情况,kmalloc会使用kmem_cache_init(预先初始化cache)初始化出来的cache,这个cache是按照size初始化(见红色字体),而不是按照类型初始化的。可见,kmem_cache既会按类型分,也会按size分。如果你调用函数kmalloc(50,GFP_KERNEL),内存开销是64字节,同理33-64都是一样的开销:64字节,知道这个有利于在内核开发时优化内存。
task_struct 356 380 5872 5 8 : tunables 0 0 0 : slabdata 76 76 0
anon_vma 6185 6400 32 128 1 : tunables 0 0 0 : slabdata 50 50 0
shared_policy_node 340 340 48 85 1 : tunables 0 0 0 : slabdata 4 4 0
numa_policy 680 680 24 170 1 : tunables 0 0 0 : slabdata 4 4 0
idr_layer_cache 690 690 544 30 4 : tunables 0 0 0 : slabdata 23 23 0
kmalloc-8192 50 56 8192 4 8 : tunables 0 0 0 : slabdata 14 14 0
kmalloc-4096 139 144 4096 8 8 : tunables 0 0 0 : slabdata 18 18 0
kmalloc-2048 331 352 2048 16 8 : tunables 0 0 0 : slabdata 22 22 0
kmalloc-1024 1339 1376 1024 32 8 : tunables 0 0 0 : slabdata 43 43 0
kmalloc-512 5574 5632 512 32 4 : tunables 0 0 0 : slabdata 176 176 0
kmalloc-256 8141 8864 256 32 2 : tunables 0 0 0 : slabdata 277 277 0
kmalloc-128 844 896 128 32 1 : tunables 0 0 0 : slabdata 28 28 0
kmalloc-64 4820 5440 64 64 1 : tunables 0 0 0 : slabdata 85 85 0
kmalloc-32 4087 4480 32 128 1 : tunables 0 0 0 : slabdata 35 35 0
kmalloc-16 11411 11776 16 256 1 : tunables 0 0 0 : slabdata 46 46 0
kmalloc-8 6078 6144 8 512 1 : tunables 0 0 0 : slabdata 12 12 0
kmalloc-192 3961 4389 192 21 1 : tunables 0 0 0 : slabdata 209 209 0
kmalloc-96 735 756 96 42 1 : tunables 0 0 0 : slabdata 18 18 0
kmem_cache_node 0 0 64 64 1 : tunables 0 0 0 : slabdata 0 0 0
详细解释参考
http://oss.org.cn/kernel-book/ch06/6.3.3.htm
Slab分配模式把对象分组放进缓冲区(尽管英文中使用了Cache这个词,但实际上指的是内存中的区域,而不是指硬件高速缓存)。因为缓冲区的组织和管理与硬件高速缓存的命中率密切相关,因此,Slab缓冲区并非由各个对象直接构成,而是由一连串的“大块(Slab)”构成,而每个大块中则包含了若干个同种类型的对象,这些对象或已被分配,或空闲,如图6.12所示。一般而言,对象分两种,一种是大对象,一种是小对象。所谓小对象,是指在一个页面中可以容纳下好几个对象的那种。例如,一个inode结构大约占300多个字节,因此,一个页面中可以容纳8个以上的inode结构,因此,inode结构就为小对象。Linux内核中把小于512字节的对象叫做小对象。
![]() |
图6.10 Slab的组成
实际上,缓冲区就是主存中的一片区域,把这片区域划分为多个块,每块就是一个Slab,每个Slab由一个或多个页面组成,每个Slab中存放的就是对象。
因为Slab分配模式的实现比较复杂,我们不准备对其进行详细的分析,只对主要内容给予描述。