释放pages的基础知识在“Buddy system基础 ”这篇文章中已经讲过了,这里主要分析释放pages的代码。
代码框架
free_pages
|----->__free_pages(virt_to_page((void *)addr), order);
| |----->__free_pages_ok(page, order);
| | |----->migratetype = get_pfnblock_migratetype(page, pfn);
| | | 获取page所属pageblock的迁移类型
| | |----->free_one_page(page_zone(page), page, pfn, order, migratetype);
| | | |----->__free_one_page(page, pfn, zone, order, migratetype);
| | | | |----->max_order = min_t(unsigned int, MAX_ORDER, pageblock_order + 1);
| | | | | 选择最大的order,当前上下文是11
| | | | |----->page_idx = pfn & ((1 << MAX_ORDER) - 1);
| | | | | 获取page在pageblock中的index
| | | | |----->buddy_idx = __find_buddy_index(page_idx, order);
| | | | | 获取其伙伴的page_index
| | | | |----->buddy = page + (buddy_idx - page_idx);
| | | | | 获取其伙伴的page
| | | | |----->if (!page_is_buddy(page, buddy, order))
| | | | | 判断当前pages与其伙伴pages能否合并,能够合并必须满足三个条件
| | | | | 1> buddy空闲,并在buddy system中
| | | | | 2> page与其buddy的order一致
| | | | | 3> page与其buddy属于相同的zone
| | | | |----->combined_idx = buddy_idx & page_idx;
| | | | | 如果可以合并,计算parent的page index
| | | | |----->page = page + (combined_idx - page_idx);
| | | | | 计算parent的page
| | | | |----->order++;
| | | | | 循环判断是否可以进一步合并parent
| | | | |----->set_page_order(page, order);
| | | | | 设置page的order
| | | | |----->list_add(&page->lru, &zone->free_area[order].free_list[migratetype]);
| | | | | 将page加入最终合并过的order对应的链表上
重要函数分析
无