Linux内存管理之初始化

       《深入理解linux内核》中对内存管理的解读比较粗略,相比之下陈莉君的书要详细很多了。如果

有人想了解内存管理的细节,可以去看看陈莉君的书,确实非常的详细。

        简单的记笔记没有什么意思,按自己的疑惑来记录吧!首先,内存管理是对全局内存进行管理的,

但是内存管理的数据也需要占内存,又是一个鸡生蛋、蛋生鸡的问题。

这个问题和内存页表建立的问题差不多的。先不谈页表吧!页表建立是在内存管理以后的。首先

知道一个东西,内存管理的一部分数据是在内核数据段或者初始段的。

        怎么看呢?有一个System.map的文件,这是编译内核之后得到的内核符号表,这张表里面有内核

重要的全局数据结构,当然很多很多的函数。以前看到过这个文件,但是没有仔细研究。一看才知道

这个文件非常的有用,它里面记录了内核代码区、数据区、初始化区的布局图,变量及函数的地址也

尽在其中。由于内核代码太过庞大,反汇编实在不是一个可行的办法。这样System.map就有了大作用

		c0923510 D contig_page_data     //在data段
		co16d598 T bootmem_node_data  	//在init段
		c094ae38 B mem_map              //在数据段

        这个文件有4万多行,我截取几个和内存管理有关的看看。上面这几个变量就是内存初始化过程中

比较重要的几个变量。这几个重要的数据结构都存在于内核的映像中,这本来应该是很明显的。但是

这样一看,感觉心里更有底了。这个鸡和蛋的问题也就有了一点眉目。既然这几个数据都在内核映像

里面,内存管理的时候,我们只需要将内核映像区标记为已用,其他的事情就不需要管了。这样就下

面就对这几个变量进行分析。

        这几个变量在内核中的定义如下:

		/*mm/bootmem.c*/
		struct pglist_data __refdata contig_page_data = {
			.bdata = &bootmem_node_data[0]
		};
		bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;

         bootmem_data_t类型的定义如下:

		typedef struct bootmem_data {
				unsigned long node_min_pfn;
				unsigned long node_low_pfn;
				void *node_bootmem_map;
				unsigned long last_end_off;
				unsigned long hint_idx;
				struct list_head list;
		} bootmem_data_t;

         为了对页面管理机制作出初步准备,Linux 使用了一种叫 bootmem 分配器(Bootmem Allocator)的

机制,这种机制仅仅用在系统引导时,它为整个物理内存建立起一个页面位图。这个位图建立在从 start_pfn

 开始的地方,也就是说,内核映像终点_end 上方的地方。这个位图用来管理低区(例如小于 896MB),

因为在 0 到 896MB 的范围内,有些页面可能保留,有些页面可能有空洞,因此,建立这个位图的目的就

是要搞清楚哪一些物理页面是可以动态分配的。bootmem_data_t结构体中的node_bootmem_map就是

一个指向位图的指针。node_boot_start 表示存放 bootmem 位图的第一个页面(即内核映像结束处的第

一个页面)。 node_low_pfn 表示物理内存的顶点,最高不超过896MB。

         变量 contig_page_data的类型就是前面介绍过的 pg_data_t 数据结构。每个 pg_data_t数据结构代

表着一片均匀的、连续的内存空间。在连续空间 UMA 结构中,只有一个节点contig_page_data,而在 

NUMA 结构或不连续空间 UMA 结构中,有多个这样的数据结构。pg_data_t 结构中有个指针 bdata,

bdata 被初始化为指向 bootmem_data_t。

         pg_data_t类型的定义如下:

		typedef struct pglist_data { 
			 zone_t node_zones[MAX_NR_ZONES]; 
			 zonelist_t node_zonelists[GFP_ZONEMASK+1]; 
			 int nr_zones; 
			 struct page *node_mem_map; 
			 unsigned long *valid_addr_bitmap; 
			 struct bootmem_data *bdata; 
			 unsigned long node_start_paddr; 
			 unsigned long node_start_mapnr; 
			 unsigned long node_size; 
			 int node_id; 
			 struct pglist_data *node_next; 
		} pg_data_t; 
           每个结构中的 node_mem_map 指向具体节点的 page 结构数组。另外一个重要的变量就是剩下的

mem_page。变量 mem_map 是类型为 struct pages 的全局稀疏矩阵。我们应该知道每一个内存页面都

有一个page变量对应它。pg_data_t中的node_mem_map变量也是一个page数组,但是它只是全局矩阵

mem_page的一部分。因为Linux要支持NUMA结构。最后一张图结束吧!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值