Compound Page
真实的页分配不仅仅是从free list上取下来就完了,复杂点不在于内存大小的分配,而是对页的分类、统计和管理。
在这里我们先看一个概念 compound page。也就是对一个跨越多个页的“组合页”。 内核对超过一个页面大小的页提供了一个方法PageCompound()来判断一个page是不是组合页的一部分。以下是内核中的注释。
/*
* Higher-order pages are called "compound pages". They are structured thusly:
*
* The first PAGE_SIZE page is called the "head page" and have PG_head set.
*
* The remaining PAGE_SIZE pages are called "tail pages". PageTail() is encoded
* in bit 0 of page->compound_head. The rest of bits is pointer to head page.
*
* The first tail page's ->compound_order holds the order of allocation.
* This usage means that zero-order pages may not be compound.
*/简单得用一个图来描述这么一个概念。
page[0] page[1] page[2] page[3]
+----------------+ +----------------+ +----------------+ +----------------+
|PG_HEAD | |_flags_1(order) | | | | |
| | | | | | | |
| | | | | | | |
| | |compound_head + | |compound_head + | |compound_head + |
+----------------+ +--------------|-+ +--------------|-+ +--------------|-+
^ | | |
| | | |
+------------------------------------+---------------------+---------------------+组合页的判断
头页面
PageHead
尾页面
PageTail
虽然叫尾页,但实际上compound page里,除了头页其余的都是尾页,不仅仅是最后一个。
是组合页
PageCompound
这是上面两者的结合,是头页或者是尾页就会返回真。
获取头页面
因为重要的信息大多存储在头页面,或者是第二个页面。所以一个组合页找到它的头页面是经常需要的工作。
其实就是从page->compound_head中取出来就好了。为什么要这么做,参考set_compound_head()。
组合页的分配和释放
设置组合页和清除组合页的方法为
prep_compound_page
free_tail_pages_check
分配流程
当我们从free list上把page拿下来,交出去前,对compound page有额外的处理。这里我们直接从get_page_from_freelist看一下这个流程。
但是出乎我意料的是,只有在分配页面时使用__GFP_COMP时才会设置compound_head。那么这么说有些“组合页”也不能用PageCompound检测出来了。
释放流程
释放过程中对compound page的处理在函数free_pages_prepare().
Last updated