老僧非是爱花红

导航

buddy之expand函数

主要内容

本文以图示方式展示buddy系统expand()算法流程,供备忘。
buddy系统从free_area[current_order]中分配页面(块)后,会调用page_alloc.c:expand()函数试图将多分配的页(块)回给buddy。

  • 内核版本 4.19.90

业精于勤荒于嬉


过程图示

初始状态

上图中 :请求分配order=2的块,实际分配了order=5的块,expand负责将本次多分配的部分内存块返还到buddy中。


结束状态
image


迭代过程
image


源码

mm/page_alloc.c

/*
 * The order of subdivision here is critical for the IO subsystem.
 * Please do not alter this order without good reasons and regression
 * testing. Specifically, as large blocks of memory are subdivided,
 * the order in which smaller blocks are delivered depends on the order
 * they're subdivided in this function. This is the primary factor
 * influencing the order in which pages are delivered to the IO
 * subsystem according to empirical testing, and this is also justified
 * by considering the behavior of a buddy system containing a single
 * large block of memory acted on by a series of small allocations.
 * This behavior is a critical factor in sglist merging's success.
 *
 * -- nyc
 */
//核心函数,释放剩余部分的页到buddy合适的zone->free_area[xxx_order]中去
//@page 分配成功的内存块的头页
//@order 请求分配的内存大小(1<<order) 
//@current_order 实际分配内存时,从1<<current_order块中分配。也就是@page所对应的内存块
//@area  @current_order对应的zone->free_area[current_order]链表
//@migratetype 请求分配的页面类型
//expand(zone, page, order, current_order, area, migratetype);
static inline void expand(struct zone *zone, struct page *page,
	int low, int high, struct free_area *area,
	int migratetype)
{
	unsigned long size = 1 << high;

	while (high > low) { //代表仍然有部分内存块需要释放到buddy
		area--;
		high--;
		size >>= 1;//size代表分配的内存块大小,size/2代表需要将size/2的块返还到buddy
		VM_BUG_ON_PAGE(bad_range(zone, &page[size]), &page[size]);

		/*
		 * Mark as guard pages (or page), that will allow to
		 * merge back to allocator when buddy will be freed.
		 * Corresponding page table entries will not be touched,
		 * pages will stay not present in virtual address space
		 */
		if (set_page_guard(zone, &page[size], high, migratetype))
			continue;
			
		//page[size]标识后半块的起始page
		list_add(&page[size].lru, &area->free_list[migratetype]);
		
		area->nr_free++;
		//调整后半块的order,此时满足size==2<<high
		set_page_order(&page[size], high);
	}
}

巨人的肩膀

https://www.codenong.com/cs105529591/

posted on 2023-01-19 21:55  老僧非是爱花红  阅读(60)  评论(0编辑  收藏  举报