linux伙伴算法实现过程分析

Linux物理内存分配有三种方式:

    a. per-CPU机制,分配单个页面,per-CPU的页缓存提供了更快的分配和释放机制;
    b. 伙伴算法,适用于分配大块连续页面(至少一个页面),解决了外碎片问题;
    c. slab机制,分配小内存,访问频率较高的内存,解决了内碎片问题。

1.伙伴算法原理及伙伴关系

为了便于页面的维护,将多个页面组成内存块,每个内存块都有 2 的方幂个页,方幂的指数被称为阶 order。order相同的内存块被组织到一个空闲链表中。伙伴系统基于2的方幂来申请释放内存页。

当申请内存页时,伙伴系统首先检查与申请大小相同的内存块链表中,检看是否有空闲页,如果有就将其分配出去,并将其从链表中删除,否则就检查上一级,即大小为申请大小的2倍的内存块空闲链表,如果该链表有空闲内存,就将其分配出去,同时将剩余的一部分(即未分配出去的一半)加入到下一级空闲链表中;如果这一级仍没有空闲内存;就检查它的上一级,依次类推,直到分配成功或者彻底失败,在成功时还要按照伙伴系统的要求,将未分配的内存块进行划分并加入到相应的空闲内存块链表. 
在释放内存页时,会检查其伙伴是否也是空闲的,如果是就将它和它的伙伴合并为更大的空闲内存块,该检查会递归进行,直到发现伙伴正在被使用或者已经合并成了最大的内存块。

满足以下条件的两个块成为伙伴:
     a. 两个块大小相同;
     b. 两个块的物理地址连续。
    伙伴算法把满足以上条件的两个块合并为一个块,为迭代算法,如果合并后的块还可以跟相邻的块进行合并,那么该算法就继续合并。

2.相关结构体

#define  MAX_ORDER  11     //空闲页面分为11个块链表,每个链表中都是固定大小的2^order页块

数据结构:

struct  free_area {
 struct  list_head  free_list[MIGRATE_TYPES];   /*双向循环链表的头,集中了大小为2^order页的空闲块对应的页描述符*/
 unsigned long  nr_free;    /*表示大小为2^order页的空闲块的个数*/
};
struct zone{
    ...
    struct free_area  free_area[MAX_ORDER];
    ...
};

伙伴算法的关系图如下:

3.分配页框

a.伙伴算法的入口函数是buffer_rmqueue:

    首先判断要分配的页面数是否为 1,如果为1 的情况下,那么并不需要从buddy系统获取,因为per-CPU的页缓存提供了更快的分配和释放机制。per-CPU cache提供了两个链表,一个是cold page链表,另外一个是hot page链表。从hot-cold 链表获取page时要考虑迁移类型。

如果per-CPU页缓存无法满足分配,那么调用rmqueue_bulk从buddy进行分配。

static inline struct page *buffered_rmqueue(struct zone *preferred_zone,
   struct zone *zone, int order, gfp_t gfp_flags,
   int migratetype)
{  ...
     if (likely(order == 
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值