3.4 初始化内存管理------《深入Linux内核架构》笔记

内存的初始化是从全局启动例程start_kernel开始的。具体流程如下图:

3.4 初始化内存管理------《深入Linux内核架构》笔记_第1张图片

setup_arch:特定于具体的体系结构,负责初始化bootmem分配器,bootmem用于在内存初始化阶段分配内存,至到伙伴系统启用,毕竟在内存初期像伙伴系统这样功能强大的内存管理是没有必要的。

setup_per_cpu_areas:SMP系统中初始化源码中定义的静态per-cpu变量,在非SMP系统中该函数为空操作。

build_all_zonelists:主要用于初始化节点中的node_zonelists成员,该成员用于在当前节点无法分配足够的内存时使用。

mem_init:停用bootmem,启动伙伴系统。

setup_per_cpu_pageset:struct zone中的pageset数组第一个数组元素分配内存


build_all_zonelists详细功能描述:


该函数主要初始化pg_data_tnode_zonelists成员,首先,将本节点的内存域按分配代价的从底到高放入node_zonelists链表(分配代价:高端内存域<普通内存域<DMA内存域),然后依次加入节点编号小于自己,和大于自己的节点的所有的域。 注意:这里只是对书(内核版本:22.6.24)本中的理解,但本人参阅的内核2.6.32.44已经有很大的改变。

特定于体系结构的设置(x86):

启动装载程序将会把内核代码拷贝到位于内存的低端地址,其边界保存变量中: _text_etext是代码段的起始和结束地址,_etext_edata之间是数据段,_edata_end之间是初始数据段(如初始化为0的全局变量),如下图:

3.4 初始化内存管理------《深入Linux内核架构》笔记_第2张图片

内核虚拟地址空间的划分如下图:

3.4 初始化内存管理------《深入Linux内核架构》笔记_第3张图片

_PAGE_OFFSEThigh_memory为直接映射的物理页帧,普通内存域便映射到该区间

VMALLOC_STARTVMALLOC_ENDvmalloc区,所开辟的内存块为建立虚拟地址连续,物理地址不连续的映射。

PersistentMappings:持久映射区,用于将高端内存的持久页映射到该区间

Fixmaps:固定映射区,每次固定映射的地址都会创建一个常数,放在一个枚举类型中,从而不会像直接映射那样有固定的公式。

对这个区间的介绍可能太过模糊了,请参阅接下来的相关文章。


注册活动内存区:

活动内存区及没有空洞的内存区,在这个功能单元主要是完成将不同内存域的边界所在页的逻辑编号保存起来,以备在free_area_init_nodes时调用。


bootmem简介:

bootmem是系统在启动过程中使用的简单内存分配器,这时指代内存的某一页并不是用struct page,因为struct page都是采用bootmem分配的空间,而是页的逻辑编号。标记一个页是否分配是采用额外的位图实现的,搜索空闲页的算法是最先适配算法。


// 2.6.32中的代码好像去掉了last_offset(上次分配的页的页内偏移)
typedef struct bootmem_data {
	unsigned long node_min_pfn; // 保存你系统中第一个页的编号,大多数体系结构为0
	unsigned long node_low_pfn;// 直接管理的内存空间的最后一页,及 ZONE_NORMAL
	void *node_bootmem_map; // 指向位图的指针
	unsigned long last_end_off; // 上一次分配的页号
	unsigned long hint_idx;
	struct list_head list;
} bootmem_data_t;




你可能感兴趣的:(算法,struct,list,活动,Build,linux内核)