伙伴系统

Posted tianzeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了伙伴系统相关的知识,希望对你有一定的参考价值。

  伙伴系统经典的内存管理方法,有效的解决了内存外部碎片问题,分配一组连续的页而建立的高效分配策略,结合2的幂次方个分配器和空闲缓冲区合并的技术。内存被分成含有若干个(2^0,2^1,2^2...2^11)页面的块。

  伙伴系统的分配器维护空闲页面所组成的块, 这里每一块都是2的方幂个页面, 方幂的指数称为阶.

概述

  1. 在分配时,如果找不到合适的块,一个大块将会被分为两部分,这两部分称为伙伴,一部分用来分配一部分是空闲,空闲的会根据页框大小插入到合适的空闲块链表中。
  2. 释放单页时,内核将CPU置于高速缓存中,会可能出现cache的页,放到“快表”的列表中。在此过程中内核判断CPU高速缓存页数是否超过一定的阈值,如果是,将一批页还给操作系统,然后将该页添加到CPU高速缓存中。
  3. 释放多页时,内核先计算该块的伙伴地址。满足一下三个条件称为伙伴:1.两块具有相同的大小,记做b;2.它们的物理地址是连续的;3.第一块的第一个页的物理地址是2*(2^b)倍数。如果找到了该内存的伙伴,并且该伙伴是空闲的,可以合并,继续检查合并后的块的伙伴是否可以继续合并。

技术图片

伙伴系统数据结构

  系统内存中的每个物理内存页(页帧),都对应于一个struct page实例, 每个内存域都关联了一个struct zone的实例,其中保存了用于管理伙伴数据的主要数数组

struct zone
{
     /* free areas of different sizes */
    struct free_area        free_area[MAX_ORDER];
};
//伙伴系统的辅助数据结构
struct free_area {
    struct list_head free_list[MIGRATE_TYPES];//是用于连接空闲页的链表. 页链表包含大小相同的连续内存区
    unsigned long nr_free;//指定了当前内存区中空闲页块的数目(对0阶内存区逐页计算,对1阶内存区计算页对的数目,对2阶内存区计算4页集合的数目,依次类推
};

  阶是伙伴系统中一个非常重要的术语. 它描述了内存分配的数量单位. 内存块的长度是2^0,order , 其中order的范围从0到MAX_ORDER

  zone->free_area[MAX_ORDER]数组中阶作为各个元素的索引, 用于指定对应链表中的连续内存区包含多少个页帧.

  • 数组中第0个元素的阶为0, 它的free_list链表域指向具有包含区为单页(2^0 = 1)的内存页面链表
  • 数组中第1个元素的free_list域管理的内存区为两页(2^1 = 2)
  • 第3个管理的内存区为4页, 依次类推,直到 2^MAXORDER-1个页面大小的块,MAXORDER默认值为11

技术图片

 

内存区的链接

  内存区中第1页内的链表元素, 可用于将内存区维持在链表中

技术图片

伙伴系统反碎片机制

内核将已分配页分为以下三种不同的类型:

  1. 不可移动页:这些页在内存中有固定的位置,不能够移动。核心内核分配的大多数内存属于该类别
  2. 可回收页:这些页不能移动,但可以删除。内核在回收页占据了太多的内存时或者内存短缺时进行页面回收。映射自文件的数据属于该类别
    kswapd守护进程会根据可回收页访问的频繁程度,周期性释放此类内存. , 页面回收本身就是一个复杂的过程. 内核会在可回收页占据了太多内存时进行回收, 在内存短缺(即分配失败)时也可以发起页面回收
  3. 可移动页:这些页可以任意移动,用户空间应用程序使用的页都属于该类别。它们是通过页表映射的。当它们移动到新的位置,页表项也会相应的更新。在内存子系统初始化期间,所有的页都被标记为可移动的

  此时内核的策略是分配一个尽可能大的连续内存块,将其从可移动列表转换到不可移动列表

  由于页无法移动, 导致在原本几乎全空的内存区中无法进行连续分配. 根据页的可移动性, 将其分配到不同的列表中, 即可防止这种情形。

以上是关于伙伴系统的主要内容,如果未能解决你的问题,请参考以下文章

BootStrap实用代码片段(持续总结)

最全最详细publiccms常用的代码片段

一道面试题目

最全最详细publiccms其他常用代码片段(内容站点)

为啥尽管源代码没有变化,但从一个系统到另一个系统的片段数量却有很大差异?

C#程序员经常用到的10个实用代码片段 - 操作系统