e_pfns_for_nodes用于计算进入ZONE_MOVABLE的内存数量.
如果kernelcore和movablecore参数都没有指定find_zone_movable_pfns_for_nodes会使ZONE_MOVABLE保持为空,该机制处于无效状态.
谈到从物理内存域提取多少内存用于ZONE_MOVABLE的问题, 必须考虑下面两种情况
- 用于不可移动分配的内存会平均地分布到所有内存结点上
- 只使用来自最高内存域的内存。在内存较多的32位系统上, 这通常会是ZONE_HIGHMEM, 但是对于64位系统,将使用ZONE_NORMAL或ZONE_DMA32.
实际计算相当冗长,也不怎么有趣,因此我不详细讨论了。实际上起作用的是结果
用于为虚拟内存域ZONE_MOVABLE提取内存页的物理内存域,保存在全局变量movable_zone中
对每个结点来说, zone_movable_pfn[node_id]表示ZONE_MOVABLE在movable_zone内存域中所取得内存的起始地址.
zone_movable_pfn定义在mm/page_alloc.c?v=4.7, line 263
static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
static bool mirrored_kernelcore;
内核确保这些页将用于满足符合ZONE_MOVABLE职责的内存分配。
3.3 实现
到现在为止描述的数据结构如何应用?
类似于页面迁移方法, 分配标志在此扮演了关键角色.
具体的实现将在3.5.4节更详细地讨论. 目前只要知道所有可移动分配都必须指定__GFP_HIGHMEM和__GFP_MOVABLE即可.
由于内核依据分配标志确定进行内存分配的内存域, 在设置了上述的标志时, 可以选择ZONE_MOVABLE内存域. 这是将ZONE_MOVABLE集成到伙伴系统中所需的唯一改变!其余的可以通过适用于所有内存域的通用例程处理, 我们将在下文讨论