Linux pglist_data、zone

      Linux内核使用结构体pglist_data 管理node中的内存资源。所有node的pglist_data结构地址都放在数组node_data中,node_states数组管理所有node的状态。( node指NUMA结构系统中的节点,其中:每个节点可以拥有多个CPU和内存等资源,

节点内使用共有的内存控制器。
节点的所有内存对于本节点的所有CPU都是等同的。
节点可分为本地节点(LocalNode)、邻居节点(Neighbour Node)和远端节点(Remote Node)

struct pglist_data *node_data[MAX_NUMNODES];//64
#defineMAX_NUMNODES (1 << CONFIG_NODES_SHIFT)
1、struct pglist_data
typedef struct pglist_data pg_data_t;
struct pglist_data{
struct zone node_zones[MAX_NR_ZONES];//4,分别对应4种zone类型:ZONE_DMA、ZONE_DMA32、ZONE_NORMAL、ZONE_MOVABLE
struct zonelist node_zonelists[MAX_ZONELIS;//2,用于分配页框时,查找从哪个zone分配
int nr_zones;//node_zones中有效zone的个数
unsigned long node_start_pfn;//node的第一个页框号
unsigned long node_present_pages;//node内的页框数,不包含洞
unsigned long node_spanned_pages;//node内的页框数,包含洞
int node_id;//当前node的编号
};
2、zone
node中的内存资源,被划分成若干zone
ZONE_DMA:物理地址16MB以下(ISA设备)
ZONE_DMA32:物理地址4GB以下(只能在4GB范围内进行DMA的32位设备)
ZONE_NORMAL:物理地址4GB以上的空间(小于4G时,没有该区域)

ZONE_MOVABLE:虚拟内存域,可移动

Linux pglist_data、zone_第1张图片

struct zone
struct zone {
int node;//当前zone所属的node编号
struct per_cpu_pageset __percpu *pageset;//针对每个cpu的,页分配高速缓存
spinlock_t lock;//保护当前zone结构的自旋锁
struct free_area free_area[MAX_ORDER];//11,空闲页框的组织结构
unsigned long *pageblock_flags;//在SPARSEMEM中,实际存储在mem_section的pageblock_flags中
struct pg_data_t *zone_pgdat;//当前zone所属node结构的指针
unsigned long zone_start_pfn;//zone的第一个页框号
unsigned long spanned_pages;//zone中的页框数,包括洞
unsigned long present_pages;//zone中的页框数,不包括洞
unsigned long managed_pages;
const char *name;//Zone的名称:"DMA","DMA32", "Normal", "Movable"
};
3、可用内存划分
   可用内存划分为两个部分:一部分用于可移动页面分配;一部分用于不可移动页面分配。(区分可移动页面区域和不可移动页面区域是为了防止不可移动页向可移动内存区域引入碎片)
可以通过配置内核命令行参数来设置两部分内存的大小:
参数kernelcore:指定用于不可移动分配的内存数量
参数movablecore:指定用于可移动分配的内存数量
当指定了kernelcore,所要求的不可移动内存将均匀地来自各个node,而剩余的内存将是可移动类别
若一个node的内存太小,则将作为不可移动内存使用
4、node_states
内核使用pglist_data结构体管理一个节点的内存资源,而使用node_states数组管理所有node的状态。
nodemask_t node_states[NR_NODE_STATES];
typedef struct
{
unsigned long bits[1];
}nodemask_t;
node_states数组中的每个元素对应一种node状态,nodemask_t 的每位bit对应一个node,共支持64个node。
enum node_states {
N_POSSIBLE,//节点在某个时间点在线
N_ONLINE,//节点在线
N_NORMAL_MEMORY,//节点有regular memory
N_HIGH_MEMORY = N_NORMAL_MEMORY,
N_MEMORY,//节点包含内存(regular,high,movable)
N_CPU,//node拥有一个或多个cpu
NR_NODE_STATES
};
5、page结构与node、zone的转换
(1)page结构的flags字段:
bit63-bit58:node编号
bit57-bit56:zone编号
(2)page_to_nid
(page->flags>> NODES_PGSHIFT) & NODES_MASK;
NODES_PGSHIFT =58 
NODES_MASK =0x3f
(3)page_zonenum
(page->flags>> ZONES_PGSHIFT) & ZONES_MASK;
ZONES_PGSHIFT= 56
ZONES_MASK =3
(4)page_zone:返回struct zone*
&node_data(page_to_nid(page))->node_zones[page_zonenum(page)];
6、页框分配时,node和zone的选择
链接:页框分配时,node和zone的选择

参考:(1)电子科大 李林老师《Linux操作系统内核技术》
            (2)《深入理解Linux内核》


你可能感兴趣的:(Linux)