Chinaunix首页 | 论坛 | 博客
  • 博客访问: 229678
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 296
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-22 11:52
文章分类

全部博文(31)

文章存档

2018年(3)

2017年(11)

2016年(12)

2015年(5)

我的朋友

分类: LINUX

2016-10-13 17:34:27

今天总结的内容主要是:
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.代码的实现

点击(此处)折叠或打开

  1. static int __build_all_zonelist(void *dummy)/*初始化整个系统的结点的zonelist*/
  2.     int nid;
  3.     for_each_online_node(nid){ /*根据nid 遍历所有的结点*/
  4.         pg_data_t *pgdat = NODE_DATA(nid);
  5.         build_zonelists(pgdat); 
  6.     }

点击(此处)折叠或打开

  1. static void __init build_zonelists(pg_data_t *pgdat){
  2.     int node,local_node;
  3.     enum zone_type i ,j ;
  4.     local_node = pgdat->node_id;
  5.     for(i = 0;i){
  6.         struct zonelist *zonelist;
  7.         zonelist = pgdat->node_zonelist + i;
  8.         j = build_zonelists_node(pgdat,zonelist,0,i); /*建立本结点内部的zone_type 是i的备用列表*/
  9.         ......
  10. /*以下两个for 循环的是结点,在build_zonelist_node 循环的是结点内部的zone_type*/
  11.         for(node = local_node + 1;node < MAX_NUMNODES; node++){ /*建立结点号比本结点高的zone_type 是i的备用列表,接在本结点内部的后面,由j来记录该从备用列表的那个位置开始记录*/
  12.             j = build_zonelist_node(NODE_DATA(node),zonelist,j,i);
  13.         }
  14.         for(node = 0;node/*建立结点号比本结点低的zone_type 是i的备用列表,接在比本结点高的后面,由j来记录该从备用列表的那个位置开始记录*/
  15.             j = build_zonelists_node(NODE_DATA(node),zonelist,j,i);
  16.         }
  17.         zonelist->zones[j] = NULL; /*最后由NULL标识*/
  18.     }
  19.     
  20. }

  21. /*每个结点内的备用列表,都是记录比本zone_type更昂贵的*/
  22. static int __init build_zonelists_node(pg_data_t *pgdat,struct zonelist* zonelist,int nr_zones,enum zone_type zone_type){
  23.     struct zone *zone;
  24.     do{
  25.         zone = pgdat->node_zones + zone_type;
  26.         if(populated_zone(zone)){
  27.             zonelist->zones[nr_zones++] = zone;
  28.         }
  29.         zone_type--;
  30.     }while(zone_type>=0) /*这里循环的是比zone_type 昂贵的内存域*/
  31.     return nr_zones;
  32. }



阅读(1656) | 评论(0) | 转发(0) |
0

上一篇:内存管理一

下一篇:example_helloword

给主人留下些什么吧!~~