对伙伴算法的理解

以前对伙伴系统算法的理解停留在理论的层次,最近通过阅读linux2.6的代码,对伙伴系统有了新的认识。

我们都知道,伙伴系统算法对内存管理的重要性,对请求连续的页框避免了外碎片起了决定性作用,对tlb缓存的刷新也起着不少作用,很大程度上避免了tlb的抖动。如果对内存分配不加以管理,因为频繁的分配不连续的,小的页框,势必引起页表的重映射,页表重映射导致tlb频繁刷新,造成对内存平均访问次数增加,系统性能下降。保存大的,连续的页框是很必要的,有些内存分配需要。为DMA分配缓存区忽略cpu,忽略分页单元,直接访问内存总线,这样势必要分配连续的内存。

伙伴系统是一个维持着若干元素的数组,一般为11个元素。每一个元素是一个指向双向链表的头指针。而每一个链表中的节点是一个指向内存区连续order个页框数目的指针。

 
 for (current_order = order; current_order < MAX_ORDER; ++current_order) {378                 area = zone->free_area + current_order;379                 if (list_empty(&area->free_list))380                         continue;381 382                 page = list_entry(area->free_list.next, struct page, lru);383                 list_del(&page->lru);384                 index = page - zone->zone_mem_map;385                 if (current_order != MAX_ORDER-1)386                         MARK_USED(index, current_order, area);387                 zone->free_pages -= 1UL << order;388                 return expand(zone, page, index, order, current_order, area);389         }

378行代码:把指针area 设置为指向order个页框链表的指针。

379行代码:判断链表是否为空,也就是所请求的order个页框链表是否为空,如果为空,从下一个元素查找。

387行代码 : 查找成功,从管理区中减掉order个页框。

212806_1ACE_1375613.png

 

 

转载于:https://my.oschina.net/u/1375613/blog/472670

这个内存分配器需要是非入侵式的,即不在要分配的内存块中写 cookie 。 而我的需求中,需要被管理的内存块都是很规则的,成 2 的整数次幂的长度。buddy memory allocation 刚好适用。 算法很简单,就是每次把一个正内存块对半切分,一直切到需要的大小分配出去。回收的时候,如果跟它配对的块也是未被使用的,就合并成一个大的块。标准算法下,分配和释放的时间复杂度都是 O(log N) ,N 不会特别大。算法的优点是碎片率很小。而且很容易做成非入侵式的,不用在被管理的内存上保存 cookie 。只需要额外开辟一个二叉树记录内存使用状态即可。 我吃完饭简单 google 了一下,没有立刻找到满足我要求的现成代码。心里估算了一下,C 代码量应该在 200 行以下,我大概可以在 1 小时内写完。所以就毫不犹豫的实现了一份。 然后,自然是开源了。有兴趣的同学可以去 github 拿一份。这样就省得到再需要时再造轮子了。嘿嘿。 btw, 当然这块代码有许多值得优化的地方,比如可以把里面的递归优化成循环回溯。这个算法我读初中时经常写。因为初一那个时候参加信息学奥赛时用的 basic 不支持局部变量,全部变量都是全局的,很难实现递归。所以早期我都不用递归遍历二叉树的,感觉写起来好麻烦。 不过循环回溯遍历树应该是比递归快不少的,因为减少了许多不必要的环境变量压栈,对不支持 closure 的 C 语言尤其是。 这个库用起来很简单。它并不实际管理内存(它不侵入被管理的内存)。你可以设想你另外有一大块内存是由许多最小单位块合起来的。你可以假设最小单位是 1K 。那么用 buddy_new(10) 就可以帮你管理 1024K 内存。 buddy_alloc 可以请求若干个最小单位块,返回一个序号。然后用户可以自己去大内存上索引出来用。用完调用 buddy_free 归还即可。 为了调试方便,我还提供了 buddy_dump 打印二叉树的细节,可以直观的看出那些内存区域未被使用,哪些已经被占用。 ps. 果然,写这篇 blog 花掉的时间比完成这些代码时间更长。代码也如我所料的没有超过 200 行。看看,把东西描述清楚就是比实现一个东西要花更长的时间,这就是项目人多反而做的慢的原因之一吧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值