Linux页框分配时,node和zone的选择

链接:Linux中的node和zone

一、页框分配时,node、zone选择方法
      zonelist order、内存策略、用户选择
1、 如何确定从哪个node分配
    (1)通过函数参数指定
    (2)通过内存策略指定
2、 如何确定从哪个zonelist搜索zone
      是否设置了__GFP_THISNODE
二、node选择
1、node选择方式
(1)Interleave
采用循环方式从设定的节点集合中选出某个节点,然后从此节点分配
(2)Bind
 设置一个节点集合
  若无__GFP_THISNODE申请标记,从本地节点分配
  若有__GFP_THISNODE申请标记,本地节点不在设定的节点集合中,从集合中最小节点号的节点处分配,本地节点在设定的节点集合中,从本地节点分配
(3)Preferred
  若设置了MPOL_F_LOCAL标志,则从本地节点分配;若未设置,则从指定的节点分配
(4)Default
从本地节点分配
2、 mempolicy(内存策略)
内核使用mempolicy结构管理内存策略
(1)struct mempolicy
struct mempolicy {
atomic_t refcnt;
unsigned short mode; 
unsigned short flags;
union {
short preferred_node;
nodemask_t nodes;
} v;
};
参数说明:
1)mode取值include\uapi\linux\mempolicy.h
MPOL_DEFAULT
MPOL_PREFERRED
MPOL_BIND
MPOL_INTERLEAVE
2)flags的取值
#defineMPOL_F_LOCAL (1 << 1)//本地分配
#defineMPOL_F_MOF  (1 << 3) /* this policywants migrate on fault */
#defineMPOL_F_MORON (1 << 4) /* Migrate On pte_numaReference On Node */
(2) 每个进程都可以有自己的内存策略, 存储在current->mempolicy字段; 若进程没有设置自己的内存策略,在分配页框时(比如调用alloc_pages),使用为当前节点预设的内存策略
struct mempolicy preferred_node_policy[MAX_NUMNODES];
每个节点一个数组项,即一个内存策略,若当前节点预设的策略为MPOL_DEFAULT,则采用default_policy,即从本地节点分配。
当处于中断上下文或者当设置了__GFP_THISNODE时,也从本地节点分配。
struct mempolicy default_policy = {
refcnt = ATOMIC_INIT(1),
mode = MPOL_PREFERRED,
flags = MPOL_F_LOCAL,
};
3、分配函数:alloc_pages_node、alloc_pages
struct page *alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order)
{
if (nid < 0)
nid = numa_node_id();
return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask));
}
struct zonelist *node_zonelist(int nid, gfp_t flags)
{
   return NODE_DATA(nid)->node_zonelists + gfp_zonelist(flags);
}
int gfp_zonelist(gfp_t flags)
{
  if (IS_ENABLED(CONFIG_NUMA) && unlikely(flags & __GFP_THISNODE))
   return 1;
 return 0;
}
调用alloc_pages_node时,node通常由用户指定。当nid<0时,使用当前节点
调用alloc_pages_node时,若gfp_mask设置了__GFP_THISNODE,使用node的结构pgdata中的node_zonelists[1],否则,使用node_zonelists[0]。
struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
{
return alloc_pages_current(gfp_mask, order);
}
alloc_pages_current中node的选择,依赖于mempolicy
三、zone选择
1、单个node
 在一个node内,除去硬性要求外(如DMA),按照优先级别,依次从:
      ZONE_MOVABLE >ZONE_NORMAL>ZONE_DMA32>ZONE_DMA
 例如:应用程序申请普通页框的过程
2、多个node
在多个node的环境中,分配方式有:Legacy方式,Node方式,Zone方式
例如:存在两个node:
node1和node2,且都只有ZONE_DMA32和ZONE_DMA
zone可能的优先级排序方式有如下几种:
(1)Legacy方式
node0中:ZONE_DMA32(0)、ZONE_DMA(0)
node1中:ZONE_DMA32(1)、ZONE_DMA(1)
即每个节点的管理结构中(如pglist_data)只排列自己的zone
(2)Node方式
在多个node间,同种zone间的优先级,和NodeDistance有关
node0中:ZONE_DMA32(0)、ZONE_DMA(0)、ZONE_DMA32(1)、ZONE_DMA(1)
node1中:ZONE_DMA32(1)、ZONE_DMA(1)、ZONE_DMA32(0)、ZONE_DMA(0)
即先排列本地节点的所有zone,然后再排列其他节点的zone
(3)Zone方式
在同一种zone中,本地node的zone优先极高
node0中:ZONE_DMA32(0)、ZONE_DMA32(1)、ZONE_DMA(0)、ZONE_DMA(1)
node1中:ZONE_DMA32(1)、ZONE_DMA32(0)、ZONE_DMA(1)、ZONE_DMA(0)
即按照zone的类型排列
3、内核选择参数设置
(1)内核命令行参数numa_zonelist_order控制zonelist order
‘zone’:宏ZONELIST_ORDER_ZONE(2)
‘node’:宏ZONELIST_ORDER_NODE(1)
'default':由内核智能选择
宏ZONELIST_ORDER_DEFAULT(0)
内核会检测各ZONE的页框数来选择Zone组织方式,当ZONE_DMA很小时,内核将倾向于选择zone方式
(2)node的结构pgdata中,node_zonelists保存了zone的优先级顺序
struct zonelist node_zonelists[2];
node_zonelists[0]:
存放按照node方式或者zone方式存储所有zone,包括其他节点的zone
node_zonelists[1]:
按照legacy方式存放本节点的所有zone
struct zonelist {
struct zonelist_cache *zlcache_ptr;
struct zoneref _zonerefs[257];//按照优先级的顺序排列zone
struct zonelist_cache zlcache;
};

struct zoneref {
struct zone *zone;//node节点内zone的地址
int zone_idx; //node节点内zone的编号
};


你可能感兴趣的:(Linux)