《操作系统导论》内存管理:Slab Allocator 和 伙伴系统 分配策略

《操作系统导论》内存管理:Slab Allocator 和 伙伴系统 分配策略

Tags
OS
Published
2022-12-28
Author
宿愿Cc

Slab Allocator

slab 分配器最早是Sun公司的J.Bonwick首先在Solaris 2.4中设计并实现了slab分配器,并将其开源,随后Linux中也实现了具有相同基本思想的同名分配器
它的主要思想如果程序频繁对一种(或多种)大小的内存,那么slab分配器就可以预先申请一大块连续的内存,然后将其切分成所需大小块的内存。
那么当需要进行内存分配的时候其实它早就准备好了合适的内存,所以在分配和释放上,它的时间是恒定的,它只需要将对象移入移出到空闲列表,同时更新引用(每个slab都会有一个引用计数,如果这个计数变成了0,则表示这个slab上的所有小块都是没有被使用的)效率是很高的。
 

外部碎片

slab分配器基本上不太会导致太多的外部内存碎片,因为对象的大小是同一类型长期使用且已经确定的。
 

内部碎片

slab分配器可能会导致少量的内部碎片,即每个slab中的buffer可能并没有被占满,正常来说内部碎片的占比不会不会超过1/n,n是slab将其分成多个n个buffer。在SunOS 5.4中,这个碎片最大被限制为12.5%,这看认为是是内部碎片和外部碎片之前权衡的最佳点
 

着色器

slab中有一个着色器的概念,因为切分后每个块其实并不是完全被使用完的,可能还有一些边角料没有被使用,这个用专业术语叫做内部碎片,着色器就是在这些边角料上做些文章。
着色器它想要做的事情其实就是让被管理的这些地址尽可能的被CPU的高速缓存命中,关于CPU高速缓存有多种策略,如直接映射高速缓存,组相联,全相联,他们都是采用不同的方式来管理缓存。但是他们的缓存思想是类似的,如都是取内存地址的具体位置来做索引(如一般都是取地址的中间位作为索引,因为高地址太容易让一组数据被映射到同一个缓存行了)。着色器就是会调整每个空闲块的首地址,使其尽量能够均匀的分配到高速缓存中
 

参考资料

 

伙伴系统

伙伴系统管理内存时,会将内存看成是的阶数,如等依次递增,且是按页来分配的,每一页的最小大小是4KB,也就意味着,这个伙伴系统最小的分配是4KB。
假设现在需要请求一个10KB大小的内存,它就会在order2( * 4 = 16)中进行查找,如果有的话,则将其返回给用户,如果没有的话,它就会在order3中查找,如果order3中有合适的块,则将其对半分成两个order2。然后将其中一个order2返回给用户,剩下的order2加入到空闲列表
当要对这个空间进行释放的时候,这个算法的优势就体现出来了,它会去看他的伙伴是否也是空闲的,如果它的伙伴也是空闲块,那么它俩就会进行合并,然后依次向上递归进行合并,直到发现伙伴是被使用的才停止。
假设我们现在要进行一个3KB的内存分配,此时内存图如下图所示,伙伴系统会帮我们找到绿色块然后进行返回
notion image
现在我们把这块区域使用完了,准备释放,此时伙伴系统会查找这个块的伙伴是否是空闲的,在我们这个示例中,这个绿色块的伙伴是没有被使用的,此时伙伴系统就会将其进行合并。
那么伙伴系统是如何确认它的伙伴的呢,其实很简单,图中绿色块其实处于8KB的起始位置,它的伙伴处于12KB的起始位置,我们可以发现,它和它的伙伴2进制位只相差了1位,如8和12是10001100,16和24是 1000011000
有关伙伴系统和slub的结合使用可以查看这个文章,描述的很详细