- 论坛徽章:
- 9
|
你好,我使用基于 ARM 架构的内存管理和您交流一下 bootmem_init_node 函数.
内核使用 meminfo 表示物理内存,meminfo 的成员 struct membank 表示一块物理内存块.
内核在启动期间会去初始化 meminfo 结构,其可以使用 uboot 传递的 ATAG 参数初始化,或者使用机器特定的 struct machine_desc 的 fixup() 函数去初始化 meminfo 结构.
正如您所描述的,分情况讨论
1. 如果我们使用一块物理内存为 1024M,那么初始化之后 meminfo->bank[0].size = 1024M,至于 meminfo->bank[0].start 的值是根据 PHYS_OFFSET 定义的.
2. 如果我们使用多块物理内存构成 1024M,那么每一块物理内存对应的一个 struct membank.
内核在 setup_arch() 函数中初始化 meminfo 之后,然后会使用 sort() 函数根据每个 membank 的起始地址从低到高的排序,其实现在 arm_memblock_init() 函数内,
排序之后 meminfo 里面的 membank 就从低地址到高地址排序.
接着内核会调用 parse_early_param() 函数,该函数要实现很多功能,其中和内存有关的作用就是设置 vmalloc_min 的值,该值代表 VMALLOC 的起始地址,该值可以通过内核参数 "vmalloc=" 来设置其大小.
设置了内核参数 "vmalloc" 的值之后就可以通过和 VMALLOC_END 获得 vmalloc_min 的具体值,
vmalloc_min 代表低端内存的最大虚拟地址,所以内核低端内存虚拟地址范围就是: PAGE_OFFSET 到 vmalloc_min .
接着内核在 paging_init() 函数的 sanity_check_meminfo() 函数中,会根据 vmalloc_min 的值,对 meminfo 中所有的 membank 进行检测.
!!!!!! 如果您启用 高端内存,也就是 CONFIG_HIGHMEM 启用,按下面情况处理.
1. membank 的范围低于 vmalloc_min 的,其 struct membank 的 highmem 成员一直为 0.
2. membank 的范围有一部分和 vmalloc_min 重叠,那么内核就将这个 membank 分作两个 membank,其中一个范围为[membank->start , vmalloc_min] ,
另外一个范围为 [vmalloc_min , (membak->start + membank->size)],低地址的 membank 的 highmem = 0,高地址的 membank 的 highmem = 1.
3. membank 的起始地址大于或等于 vmalloc_min,那么就将其 membank 的 highmem = 1.
!!!!!! 如果没有启用 高端内存,那么按下面处理.
1. membank 的范围低于 vmalloc_min 的,其 struct membank 的 highmem 成员一直为 0.
2. membank 的范围有一部分和 vmalloc_min 重叠,那么内核就将大于 vmalloc_min 的地址忽略,其 membank 的范围变成 [membank->start , vmalloc_min].
3. membank 的起始地址大于或等于 vmalloc_min,直接忽略.
通过 sanity_checnk_meminfo() 函数之后,在支持高端内存的系统中,membank 被分作了 highmem = 0 的低端内存 和 highmem = 1 的高端内存.
处理完 meminfo 之后,内核就开始映射页表.
初始化页表时,只有第一块 membank 可以进行映射!!!!尽管其他属于低端内存的 membank,但其不进行页表映射. |
|