Linux 伙伴算法简介
本文将简要介绍一下Linux内核中的伙伴分配算法。
算法作用
它要解决的问题是频繁地请求和释放不同大小的一组连续页框,必然导致在已分配页框的块内分散了许多小块的空闲页面,由此带来的问题是,即使有足够的空闲页框可以满足请求,但要分配一个大块的连续页框可能无法满足请求。
伙伴算法(Buddy system)把所有的空闲页框分为11个块链表,每块链表中分布包含特定的连续页框地址空间,比如第0个块链表包含大小为2^0个连续的页框,第1个块链表中,每个链表元素包含2个页框大小的连续地址空间,….,第10个块链表中,每个链表元素代表4M的连续地址空间。每个链表中元素的个数在系统初始化时决定,在执行过程中,动态变化。
伙伴算法每次只能分配2的幂次页的空间,比如一次分配1页,2页,4页,8页,…,1024页(2^10)等等,每页大小一般为4K,因此,伙伴算法最多一次能够分配4M的内存空间。
核心概念和数据结构
两个内存块,大小相同,地址连续,同属于一个大块区域。(第0块和第1块是伙伴,第2块和第3块是伙伴,但第1块和第2块不是伙伴)
伙伴位图:用一位描述伙伴块的状态位码,称之为伙伴位码。比如,bit0为第0块和第1块的伙伴位码,如果bit0为1,表示这两块至少有一块已经分配出去,如果bit0为0,说明两块都空闲,还没分配。
Linux2.6为每个管理区使用不同的伙伴系统,内核空间分为三种区,DMA,NORMAL,HIGHMEM,对于每一种区,都有对于的伙伴算法,
1. free_area数组:

1: struct zone{
2: ....
3: struct free_area free_area[MAX_ORDER];
4: ....
5: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
struct free_area free_area[MAX_ORDER] #MAX_ORDER 默认值为11
2. zone_mem_map数组

free_area数组中,第K个元素,它标识所有大小为2^k的空闲块,所有空闲快由free_list指向的双向循环链表组织起来。其中的nr_free,它指定了对应空间剩余块的个数。
整个分配图示,大概如下:

申请和回收过程
比如,我要分配4(2^2)页(16k)的内存空间,算法会先从free_area[2]中查看nr_free是否为空,如果有空闲块,则从中分配,如果没有空闲块,就从它的上一级free_area[3](每块32K)中分配出16K,并将多余的内存(16K)加入到free_area[2]中去。如果free_area[3]也没有空闲,则从更上一级申请空间,依次递推,直到free_area[max_order],如果顶级都没有空间,那么就报告分配失败。
释放是申请的逆过程,当释放一个内存块时,先在其对于的free_area链表中查找是否有伙伴存在,如果没有伙伴块,直接将释放的块插入链表头。如果有或板块的存在,则将其从链表摘下,合并成一个大块,然后继续查找合并后的块在更大一级链表中是否有伙伴的存在,直至不能合并或者已经合并至最大块2^10为止。
内核试图将大小为b的一对空闲块(一个是现有空闲链表上的,一个是待回收的),合并为一个大小为2B的单独块,如果它成功合并所释放的块,它会试图合并2b大小的块,
内核使用_rmqueue()函数来在管理区中找到一个空闲块,成功返回第一个被分配页框的页描述符,失败返回NULL。

内核使用
__free_pages_bulk()函数按照伙伴系统的策略释放页框。它使用3个基本输入参数:
page:被释放块中所包含的第一个页框描述符的地址。
zone:管理区描述符的地址。
order:块大小的对数。
伙伴算法的优缺点
优点:
较好的解决外部碎片问题
当需要分配若干个内存页面时,用于DMA的内存页面必须连续,伙伴算法很好的满足了这个要求
只要请求的块不超过512个页面(2K),内核就尽量分配连续的页面。
针对大内存分配设计。
缺点:
1. 合并的要求太过严格,只能是满足伙伴关系的块才能合并,比如第1块和第2块就不能合并。
2. 碎片问题:一个连续的内存中仅仅一个页面被占用,导致整块内存区都不具备合并的条件
3. 浪费问题:伙伴算法只能分配2的幂次方内存区,当需要8K(2页)时,好说,当需要9K时,那就需要分配16K(4页)的内存空间,但是实际只用到9K空间,多余的7K空间就被浪费掉。
4. 算法的效率问题: 伙伴算法涉及了比较多的计算还有链表和位图的操作,开销还是比较大的,如果每次2^n大小的伙伴块就会合并到2^(n+1)的链表队列中,那么2^n大小链表中的块就会因为合并操作而减少,但系统随后立即有可能又有对该大小块的需求,为此必须再从2^(n+1)大小的链表中拆分,这样的合并又立即拆分的过程是无效率的。
Linux针对大内存的物理地址分配,采用伙伴算法,如果是针对小于一个page的内存,频繁的分配和释放,有更加适宜的解决方案,如slab和kmem_cache等,这不在本文的讨论范围内。
参考链接:伙伴算法剖析(原创)
Linux 伙伴算法简介的更多相关文章
- Linux伙伴算法
Linux内存管理伙伴算法 伙伴算法 Linux内核内存管理的任务包括: 遵从CPU的MMU(Memory Management Unit)机制 合理.有效.快速地管理内存 实现内存保护机制 实现虚拟 ...
- 内存管理算法--Buddy伙伴算法【转】
转自:http://blog.csdn.net/orange_os/article/details/7392986 Buddy算法的优缺点: 1)尽管伙伴内存算法在内存碎片问题上已经做的相当出色,但是 ...
- PageRank 算法简介
有两篇文章一篇讲解(下面copy)< PageRank算法简介及Map-Reduce实现>来源:http://www.cnblogs.com/fengfenggirl/p/pagerank ...
- 伙伴算法与slab算法
伙伴算法: 1.将空闲页面分为m个组,第1组存储2^0个单位的内存块,,第2组存储2^1个单位的内存块,第3组存储2^2个单位的内存块,第4组存储2^3个单位的内存块,以此类推.直到m组. 2.每个组 ...
- 新一代 Linux 文件系统 btrfs 简介
https://www.ibm.com/developerworks/cn/linux/l-cn-btrfs/ Btrfs 简介 文件系统似乎是内核中比较稳定的部分,多年来,人们一直使用 ext2/3 ...
- Linux C++ 开发简介
主要介绍将Windows程序迁移到Linux系统相关知识 简介 Windows程序迁移到Linux系统可能需要修改很多代码, 既需要了解Linux平台的开发知识, 也需要了解Windows平台代码如何 ...
- webrtc 的回声抵消(aec、aecm)算法简介(转)
webrtc 的回声抵消(aec.aecm)算法简介 webrtc 的回声抵消(aec.aecm)算法主要包括以下几个重要模块:1.回声时延估计 2.NLMS(归一化最小均方自适应算法) ...
- 内存管理算法--Buddy伙伴算法
Buddy算法的优缺点: 1)尽管伙伴内存算法在内存碎片问题上已经做的相当出色,但是该算法中,一个很小的块往往会阻碍一个大块的合并,一个系统中,对内存块的分配,大小是随机的,一片内存中仅一个小的内存块 ...
- AES算法简介
AES算法简介 一. AES的结构 1.总体结构 明文分组的长度为128位即16字节,密钥长度可以为16,24或者32字节(128,192,256位).根据密钥的长度,算法被称为AES-128,AES ...
随机推荐
- 分享10款常用的jQuery焦点图插件
爱编程一直在收集整理编程相关的知识和解决方案,今天小编为大家带来10款非常常用的jquery焦点图插件. 1.jQuery可自动播放动画的焦点图插件 之前我们已经分享过很多非常实用的jQuery焦点图 ...
- spring security源码分析之core包
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring I ...
- Android 在onActivityResult()中设置图片setImageResource(resId) 或者改变view属性,不成功的解决办法
如果试验过的朋友就会发现,在onActivityResult()中设置这些属性,好像都不工作,虽然我死磕一番还是不知道具体原因,我直接默认它可能就是不能在里面设置,所以就只能在其他地方设置,幸好发现A ...
- HTML5图片拖拽预览原理及实现
一.前言 这两天恰好有一位同事问我怎样做一个图片预览功能.作为现代人的我们首先想到的当然是HTML5啦,其实HTML5做图片预览已经是一个老生常谈的问题了.我在这里就简单说说其中相关的一些东西,当然会 ...
- iOS开发 - 一个天真的搜索控制器的独白
文/Azen(简书作者)原文链接:http://www.jianshu.com/p/6d5327111511著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 正文 一.关于横向模块开发 ...
- 【Android 界面效果15】Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
Android开发做到了一定程度,多少都会用到自定义控件,一方面是更加灵活,另一方面在大数据量的情况下自定义控件的效率比写布局文件更高. 一个相对完善的自定义控件在布局文件中和java ...
- Communications link failure的解决办法
使用Connector/J连接MySQL数据库,程序运行较长时间后就会报以下错误: Communications link failure,The last packet successfully r ...
- 放飞App:移动产品经理实战指南
<放飞App:移动产品经理实战指南> 基本信息 原书名:App savvy:rurning ideas into iPhone and iPad Apps customers really ...
- VMware系统运维(二十)部署虚拟化桌面Horzion View 5.2 HTML Access进行连接测试
1.通过浏览器打开Horzion View登录界面,https://conntionserver.testad.local,点击"VMware Horzion View HTML Acces ...
- Bash中的位置参数和特殊参数
#Bash中的位置参数和特殊参数 #Bash中的位置参数是由0以外的一个或多个数字表示的参数.#位置参数是当Shell或Shell函数被引用时由Shell或Shell函数的参数赋值,并且可以使用Bas ...