今天总结的内容主要是:
struct pglist_data (表示内存结点的数据结构)的备用结点内存域列表的初始化 ,就是pglist_data->node_zonelists[] 数组的初始化
1. 数据结构的关系如下
struct pglist_data{
..........
struct zonelist node_zonelists[MAX_ZONELISTS];
}pg_data_t;
#define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES)
struct zonelist{
.........
struct zone *zone[MAX_ZONES_PER_ZONELIST+1];
};
node_zonelist[] 与内存域node_zones[]数组对应,每一个内存域zone会有一个zonelist
这个备用列表的初始化,就是填充每个内存域对应的zonelist中的zone 成员
2.备用列表的选择原则
三种内存域DMA,NORMAL,HIGMEM由于作用不同,所以会有廉价和昂贵之分
DMA,因为用于外设和系统之间的数据传输,因此是最昂贵的
NORMAL,许多内核数据结构必须保持在该内存域,而不能放到高端内存域中,所以相对来说普通的内存域比高端内存域要昂贵
HIGMEM,是最廉价的,因为内核没有任何部分依赖于该内存域,如果高端内存用尽对内核没有任何副作用
备用列表内存域的选择是从廉价到昂贵的,因此,三种内存域的选择顺序依次是HIGMEM(2),NORMAL(1),DMA(0)
选择原则:
结点内的内存域选择是从本内存域开始,然后选择比自己昂贵的
结点的选择是从本结点开始,然后往结点号增加的方向选择,如果结点号增加的方向没有合适,再从结点号为0的结点开始选择。
例子,系统有四个结点分别是A,B,C,D,每个结点都有三个内存域,分别是DMA(0),NORMAL(1),HIGMEM(2).
DMA,NORMAL,HIGMEM的大小是根据enum zone_type 枚举来决定的。
结点C的DMA,NORMAL,HIGMEM的备用列表分别如下:
如果内核需要分配普通内存,那么内核会在当前结点(假设是C结点)的NORMAL 内存域中寻找大小适当的空闲段,如果分配失败,那么就会到C结点的DMA域(C0)中分配,如果每次都失败,那么分配的顺序就是C1->C0->D1->D0->A1->A0->B1->B0
3.代码的实现
-
static int __build_all_zonelist(void *dummy){/*初始化整个系统的结点的zonelist*/
-
int nid;
-
for_each_online_node(nid){ /*根据nid 遍历所有的结点*/
-
pg_data_t *pgdat = NODE_DATA(nid);
-
build_zonelists(pgdat);
-
}
-
}
-
static void __init build_zonelists(pg_data_t *pgdat){
-
int node,local_node;
-
enum zone_type i ,j ;
-
local_node = pgdat->node_id;
-
for(i = 0;i){
-
struct zonelist *zonelist;
-
zonelist = pgdat->node_zonelist + i;
-
j = build_zonelists_node(pgdat,zonelist,0,i); /*建立本结点内部的zone_type 是i的备用列表*/
-
......
-
/*以下两个for 循环的是结点,在build_zonelist_node 循环的是结点内部的zone_type*/
-
for(node = local_node + 1;node < MAX_NUMNODES; node++){ /*建立结点号比本结点高的zone_type 是i的备用列表,接在本结点内部的后面,由j来记录该从备用列表的那个位置开始记录*/
-
j = build_zonelist_node(NODE_DATA(node),zonelist,j,i);
-
}
-
for(node = 0;node/*建立结点号比本结点低的zone_type 是i的备用列表,接在比本结点高的后面,由j来记录该从备用列表的那个位置开始记录*/
-
j = build_zonelists_node(NODE_DATA(node),zonelist,j,i);
-
}
-
zonelist->zones[j] = NULL; /*最后由NULL标识*/
-
}
-
-
}
-
-
/*每个结点内的备用列表,都是记录比本zone_type更昂贵的*/
-
static int __init build_zonelists_node(pg_data_t *pgdat,struct zonelist* zonelist,int nr_zones,enum zone_type zone_type){
-
struct zone *zone;
-
do{
-
zone = pgdat->node_zones + zone_type;
-
if(populated_zone(zone)){
-
zonelist->zones[nr_zones++] = zone;
-
}
-
zone_type--;
-
}while(zone_type>=0) /*这里循环的是比zone_type 昂贵的内存域*/
-
return nr_zones;
-
}
阅读(1701) | 评论(0) | 转发(0) |