分配内核内存(buddy系统和slab系统)(3)

目录

  1. 内存管理中的分区分配方法(1)
  2. 伙伴系统(算法)-内存分配技术(2)
  3. 分配内核内存(buddy系统和slab系统)(3)

管理内核进程空闲内存的两种策略:

1. 伙伴系统 –

伙伴分配系统是一种算法,它把一个大的内存块切分为一个小的部分来满足请求。该算法通常给出最符合的内存块。块的两个更小的子部分是相同大小的,称为伙伴。两个伙伴中的一个以同样的方式进一步切分为更小的子部分,直到请求被满足为止。该技术的好处是两个伙伴可以根据内存请求合并形成一个大尺寸的块。
例如 – 如果发出一个需求25Kb的请求,那么被分配到的块的大小为32Kb。
1

四种类型的伙伴系统 –

  1. 二分伙伴系统
  2. 斐波那契伙伴系统
  3. 权重伙伴系统
  4. 三级伙伴系统

2
上图取自:https://www.semanticscholar.org/paper/Tertiary-buddy-system-for-efficient-dynamic-memory-Yadav-Sharma/600765f1309dedb9b42290149b2cf098f0044218/figure/5

为什么伙伴系统?

如果分区大小与进程(需求)大小是不同的,则会出现不匹配情况,并且可能无法有效的使用空间。
动态分配实现简单并且高效。

二分伙伴系统 –

伙伴系统为每个尺寸(称为空闲列表)的空闲块维护一个列表,因此它很容易找到一个期望尺寸的块,如果有一个是可用的。如果没有请求的块是可用的,分配查找具有请求的最低限度的块的第一个非空列表。在两种情况下,都会从空闲列表中移除一个块。

案例 –

假设内存的段大小初始值是256kb,并且内核请求25kb的内存。这个段初始切分为两个伙伴。我们称其为A1和A2每个大小为128kb。这两个伙伴中的一个进一步切分到两个64kb的伙伴称为B1和B2。但是25kb下一个高(2)次幂是32kb,所以,或者B1或者B2进一步切分到两个32kb的伙伴(C1 and C2)并且最终使用两个伙伴中的一个来满足25kb的请求。一个分割块只能与它的唯一伙伴块进行合并,然后再形成一个更大的块,更大的块即他们从哪切分过来的(父节点)。

斐波那契伙伴系统 –

该系统的块被按照斐波那契数列数字的大小进行切分。它满足下面的关系:

Z = Z+Z

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 144, 233, 377, 610。二分和权重伙伴系统的地址计算非常简单,但是斐波那契伙伴系统开始过程要么被限制在一个小的,固定数量的块大小上,要么就是一个耗时的计算。

优势 –

  • 相比较其他简单的动态分配技术,伙伴内存系统的外部碎片很小。
  • 伙伴内存分配系统使用二叉树实现表示已使用或未使用的切分的内存块。
  • 伙伴系统分配或释放内存方面非常的快。
  • 在伙伴系统中,分配与释放一个快的内存相比“最符合”或“第一符合”算法成本要低。
  • 另一个优势是合并。
  • 地址计算简单。

什么是合并?

它的定义是:如何快速的把相邻伙伴合并形成更大的段被称为合并。
例如,当内核释放了分配给它的C1单元,系统可以聚合C1与C2为64kb段。该段B1可以与它的伙伴B2聚合形成128kb的段。最终我们可以结束在开始的256kb段。

缺点Drawback –

在伙伴系统中主要的缺点是内部碎片,因为需要获得更大的内存块。例如如果发出一个36kb的请求,它只能由64kb的段满足并且剩余的内存被浪费。

2. Slab分配 –

描述

为内核内存分配的第二个策略称为slab分配。它消除了由分配与释放引起的碎片。该方法通常保留包含了确定类型的数据对象已分配内存,为了后续的同类型对象的分配重用。在slab分配中,内存块适合于确定类型或大小的适合的数据对象的预分配。在使用完之后Cache不会立即释放空间,尽管它保持跟踪频繁需要的数据,因此无论何时发出请求,该数据将会很快到达(触达)。两个需要的术语:

  • Slab – A slab由一个或多个物理连续的分页组成。The slab实际上是数据与关联的特殊类型的包含缓存的对象的容器。
  • Cache – Cache表示少量非常快的内存。A cache有一个或多个slabs组成。每个唯一的内核数据结构都有一个单独的cache。

3

案例 –

  • 为表示进程描述符数据结构的单独缓存。
  • 文件对象的单独缓存。
  • 信号量等等的单独缓存。

每个缓存都填有对象,这些对象是缓存所代表的内核数据结构的实例化。例如代表信号量的缓存存储信号量对象,代表进程描述符的缓存存储进程描述符对象的实例。

实现 –

slab分配算法使用缓存存储内核对象。缓存创建时,许多初始标记为空闲的对象分配给缓存。缓存中对象的数量依赖于关联slab的大小。
案例 – A 12 kb的slab(由3个连续的4kb分页组成)可以存储6个2 kb对象。初始化时所有缓存中的对象被标记为空闲。当一个内核数据结构的新对象需要时,分配器可以从缓存中分配一些空闲的对象满足请求。从缓存中分配的对象被标记为已使用。
在linux中,一个slab可能处于三种状态之一:

  1. Full – 所有slab中的对象都被标记为已使用
  2. Empty – 所有slab中的对象都被标记为空闲
  3. Partial – slab由部分已使用对象与部分空闲对象组成

slab分配器首先尝试使用partial slab中的一个空闲对象来满足请求。如果不存在,则从一个empty slab中分配一个空闲对象。如果没有empty slabs是可用的,则从连续的物理分页中分配一个新的slab并将其分配给一个缓存。

slab分配器的益处 –

  • 没有由于碎片浪费内存,因为每个唯一的内核数据结构都有一个关联的缓存。
  • 可以快速满足内存请求。
  • 当管理频繁分配或释放的对象时slab分配方案是尤其高效。分配与释放内存动作可能是一个耗时的过程。但是,对象是预先创建的,因此可以从缓存中快速分配。当内核终结一个对象并且释放它时,它被标记为空闲并返回给它的缓存,从而使它立即可用于内核的后续请求。

原文

第一部分:https://www.geeksforgeeks.org/partition-allocation-methods-in-memory-management/
第二部分:https://www.geeksforgeeks.org/buddy-system-memory-allocation-technique/
第三部分:https://www.geeksforgeeks.org/operating-system-allocating-kernel-memory-buddy-system-slab-system/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章