伙伴系统
Posted tianzeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了伙伴系统相关的知识,希望对你有一定的参考价值。
伙伴系统经典的内存管理方法,有效的解决了内存外部碎片问题,分配一组连续的页而建立的高效分配策略,结合2的幂次方个分配器和空闲缓冲区合并的技术。内存被分成含有若干个(2^0,2^1,2^2...2^11)页面的块。
伙伴系统的分配器维护空闲页面所组成的块, 这里每一块都是2的方幂个页面, 方幂的指数称为阶.
概述:
- 在分配时,如果找不到合适的块,一个大块将会被分为两部分,这两部分称为伙伴,一部分用来分配一部分是空闲,空闲的会根据页框大小插入到合适的空闲块链表中。
- 释放单页时,内核将CPU置于高速缓存中,会可能出现cache的页,放到“快表”的列表中。在此过程中内核判断CPU高速缓存页数是否超过一定的阈值,如果是,将一批页还给操作系统,然后将该页添加到CPU高速缓存中。
- 释放多页时,内核先计算该块的伙伴地址。满足一下三个条件称为伙伴: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页内的链表元素, 可用于将内存区维持在链表中
伙伴系统反碎片机制
内核将已分配页分为以下三种不同的类型:
- 不可移动页:这些页在内存中有固定的位置,不能够移动。核心内核分配的大多数内存属于该类别
- 可回收页:这些页不能移动,但可以删除。内核在回收页占据了太多的内存时或者内存短缺时进行页面回收。映射自文件的数据属于该类别
kswapd守护进程会根据可回收页访问的频繁程度,周期性释放此类内存. , 页面回收本身就是一个复杂的过程. 内核会在可回收页占据了太多内存时进行回收, 在内存短缺(即分配失败)时也可以发起页面回收 - 可移动页:这些页可以任意移动,用户空间应用程序使用的页都属于该类别。它们是通过页表映射的。当它们移动到新的位置,页表项也会相应的更新。在内存子系统初始化期间,所有的页都被标记为可移动的
此时内核的策略是分配一个尽可能大的连续内存块,将其从可移动列表转换到不可移动列表。
由于页无法移动, 导致在原本几乎全空的内存区中无法进行连续分配. 根据页的可移动性, 将其分配到不同的列表中, 即可防止这种情形。
以上是关于伙伴系统的主要内容,如果未能解决你的问题,请参考以下文章