以前对伙伴系统算法的理解停留在理论的层次,最近通过阅读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个页框。