Linux 内核高-低端内存设置代码跟踪(ARM构架)

对于ARM中内核如何在启动的时候设置高低端内存的分界线(也是逻辑地址与虚拟地址分界线(虚拟地址)减去那个固定的偏移),这里我稍微引导下(内核分析使用Linux-3.0):

首先定位设置内核虚拟地址起始位置(也就是内核逻辑地址末端+1的地址)的文件:init.c (arch\arm\mm),在这个文件中的void __init bootmem_init(void)函数如下

这个high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) – 1) + 1;语句就是关键。从这里可以知道max_low就是高端内存的起始地址(物理地址)。那么这个max_low是如何得到的?其实看上面的代码可以推测出,他其实是在find_limits(&min, &max_low, &max_high);中(在同一个文件中)被设置的:

这个函数的意思很明显:通过扫描struct meminfo *mi = &meminfo;(结构体meminfo的数组)中的所有信息,设置三个指针所指的变量:

min :内存物理地址起始
max_low :低端内存区物理地址末端
max_high :高端内存区物理地址末端

从上面可以看出,max_low和max_high所保存的地址不同就是由于bank->highmem造成的,它是内存bank被设为高端内存的依据:

“如果这个内存bank是高端内存(bank->highmem != 0),跳过max_low = end;语句,max_low和max_high将不同(结果实际上是max_high > max_low);
否则假设没有一个内存bank是高端内存(所有bank->highmem == 0)max_low和max_high必然一致(高端内存大小为0)”

当然要实现这个函数的功能,必须保证meminfo所指数组中的所有bank是按照地址数据从小到大排序好的哦~~。但是这个大家不用担心,后面会看到的:)

经过上面的跟踪,焦点集中到了全局变量(同一个文件中):

/*
* This keeps memory configuration data used by a couple memory
* initialization functions, as well as show_mem() for the skipping
* of holes in the memory map. It is populated by arm_add_memory().
*/
struct meminfo meminfo;

这个结构体的定义(setup.h (arch\arm\include\asm)):

只要找到初始化这个全局变量并完成排序的地方,就可以知道高端内存是如何配置的了!!OK,明确目标,go on~~~

通过查找代码,我们可以在setup.c (arch\arm\kernel)这个文件中找到相关的代码。在系统启动早期会运行的函数(具体的顺序你可以自行分析下ARM内核的启动流程,以后我也会写下)中有这样一个函数:

在上面的注释中,我已经表明了重点和解析,下面我细化下:

(1)获取参数部分

通过parse_early_param();函数可以解析内核启动参数中的许多字符串,但是对于我们这次分析内存的话主要是分析以下两个参数:
mem=size@start参数,她为初始化struct meminfo meminfo;(我们一直关注的内存信息哦~)提供信息。具体的获取信息的函数(同样位于setup.c (arch\arm\kernel))

vmalloc=size参数,她为初始化vmalloc_min(需要保留的内核虚拟地址空间大小,也就是这个内核虚拟地址空间中除去逻辑地址空间和必要的防止越界的保护空洞后最少要预留的地址空间)提供信息。具体的实现函数(位于mmu.c (arch\arm\mm)):

(2)在获得了必要的信息(初始化好struct meminfo meminfo和vmalloc_min)后,内核通过sanity_check_meminfo函数自动去通过vmalloc_min信息来初始化每个meminfo.bank[?]中的highmem成员。此过程中如果有必要,将可能会改变meminfo中的bank数组。处理函数位于mmu.c (arch\arm\mm)

(3)最后必须做的就是排序了,完成了这个工作就可以完全被我们上面提到的find_limits函数使用了,而这个工作就放在了接下来的arm_memblock_init(&meminfo, mdesc);中的一开头:

通过上面的分析,整个高低端内存是如何确定的基本就清晰了,这里总结一下:

ARM构架中,高-低段内存是内核通过内核启动参数( mem=size@start和vmalloc=size)来自动配置的,如果没有特殊去配置他,那么在普通的ARM系统中是不会有高端内存存在的。除非你系统的RAM很大或vmalloc配置得很大,就很可能出现高端内存。

以上是我对高-低端内存学习时跟踪代码的备忘,如果大家在其中发现什么不对的地方,欢迎拍砖、纠正~~谢谢~

1 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部