linux系统启动时的内存操作之二——伙伴算法

1。算法原理

Buddy System是一种经典的内存管理算法。在Unix和Linux操作系统中都有用到。其作用是减少存储空间中的空洞、减少碎片、增加利用率。避免外碎片的方法有两种:

a.利用分页单元把一组非连续的空闲页框映射到非连续的线性地址区间。

b.开发适当的技术来记录现存的空闲连续页框块的情况,以尽量避免为满足对小块的请求而把大块的空闲块进行分割

基于下面三种原因,内核选择第二种避免方法:

a.在某些情况下,连续的页框确实必要。

b.即使连续页框的分配不是很必要,它在保持内核页表不变方面所起的作用也是不容忽视的。假如修改页表,则导致平均访存次数增加,从而频繁刷新TLB。

c.相对于小页的使用,通过访问大块连续的物理内存,TLB未命中率降高,加快平均访存速度。

buddy算法将所有空闲页框分组为10种块链表,大小分别为1,2,4,8,16,32,64,128,256,512个连续的页框,每个块的第一个页框的物理地址是该块大小的整数倍。如,大小为16个页框的块,其起始地址是16*2^12的倍数。

例,假设要请求一个128个页框的块,算法先检查128个页框的链表是否有空闲块,如果没有则查256个页框的链 表,有则将256个页框的块分裂两份,一份使用,一份插入128个页框的链表。如果还没有,就查512个页框的链表,有的话就分裂为 128,128,256,一个128使用,剩余两个插入对应链表。如果在512还没查到,则返回出错信号。

回收过程相反,内核试图把大小为b的空闲伙伴合并为一个大小为2b的单独块,满足以下条件的两个块称为伙伴:

a.两个块具有相同的大小,记做m。

b.它们的物理地址是连续的。

c.第一个块的第一个页框的物理地址是2*m*2^12的倍数(每个页的大小为2^12)。

该算法迭代,如果成功合并所释放的块,会试图合并2b的块来形成更大的块。

2。buddy算法在linux中的应用

Linux内核对各个zone都有一个buddysystem。

struct zone中的unsigned long free_pages保存的是空闲块的大小。

特别强调的是struct free_area free_area[MAX_ORDER],保存着zone中的空闲块。数组中的每一个元素都有个双链表结构。

struct free_area {

  • struct list_head free_list;
  • unsigned long nr_free;

};

比如说 free_area中第K个元素保存着大小为2的k次方大小的块的链表结构。数组中保存的是表头结构,即指向第一个2的k次方大小块的第一个页面。那块的 剩余的页面怎么办?不用管,因为都是按块来操作的,只需要知道块的第一个页面即可,最后一个页面就是第一个页面加上2的k次方。同属于一个链表的块与块之 间由每一个块的第一个页面的struct page 中的list_head lru来相互链接。

分配一个大小为2的m次方的页面块,首先看freearea的第m个元素,如果其nr_free大于0,则从这个链表中取出来一个块来满足要求,如果不大于0,则看数组中m+1个元素,一直这样找下去。如果找到能够分配的,那么就将块的第一部分大小为2的m次方的块分出 去,剩下的继续保存在buddysystem中。

而每一个zone结构里都有一个struct pglist_data *zone_pgdat域,这个域的成员struct page *node_mem_map指向这个zone的第一个page 在mem_map的位置,mem_map是一个struct page指针,对应系统中所有的物理内存页。

页面分配代码使用free_area数组来寻找和释放页面,此机制负责整个缓冲管理。另外此代码与处理器使用的页面大小和物理分页机制无关。

free_area 中的每个元素都包含页面块的信息。数组中第一个元素描叙1个页面,第二个表示2个页面大小的块 而接下来表示4个页面大小的块,总之都是2的次幂倍大小。list域表示一个队列头,它包含指向mem_map指针中page数据结构的指针。所有的空闲 页面都在此队列中。map域是指向某个特定页面尺寸的页面组分配情况位图的指针。当页面的第N块空闲时,位图的第N位被置位。

2.1页面分配

Linux 使用Buddy算法来有效的分配与回收页面块。页面分配代码每次分配包含一个或者多个物理页面的内存块。页面以2的次幂的内存块来分配。这意味着它可以分配1个、2个和4个页面的块。只要系统中有足够的空闲页面来满足这个要求 (nr_free_pages > min_free_page),内存分配代码将在free_area中寻找一个与请求大小相同的空闲块。free_area中的每个元素保存着一个反映这 样大小的已分配与空闲页面 的位图。例如,free_area数组中第二个元素指向一个反映大小为四个页面的内存块分配情况的内存映象。

分配算法首先搜寻满足请求大小的页面。它从free_area数据结构的list域着手沿链来搜索空闲页面。如果 没有这样请求大小的空闲页面,则它搜索两倍于请求大小的内存块。这个过程一直将持续到free_area 被搜索完或找到满足要求的内存块为止。如果找到的页面块大于请求的块则对其进行分割以使其大小与请求块匹配。由于块大小都是2的次幂所以分割过程十分简 单。空闲块被连进相应的队列而这个页面块被分配给调用者。

相应的队列而这个页面块被分配给调用者。

2.2页面回收

将大的页面块打碎进行分配将增加系统中零碎空闲页面块的数目。页面回收代码在适当时机下要将这些页面结合起来形成单一大页面块。事实上页面块大小决定了页面重新组合的难易程度。

当页面块被释放时,代码将检查是否有相同大小的相邻或者buddy内存块存在。如果有,则将它们结合起来形成一个大小为原来两倍的新空闲块。每次结合完之后,代码还要检查是否可以继续合并成更大的页面。最佳情况是系统的空闲页面块将和允许分配的最大内存一样大。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值