我正在学习专业的 Linux 内核架构,我在第 3 章内存管理。而我研究内核地址空间本身分为直接映射区、vmalloc区、kmap区和固定映射区。
我想知道的是就像下面一样。
32位机器中内核地址空间的直接映射区域(896MB)是否可以在没有MMU的情况下被__va、__pa之类的函数访问?
如果 1. 为真,那么主内核页表(swapper_pg_dir)只管理 128MB 吗?
在研究内核代码时,我发现 32 位和 64 位之间的 paging_init 函数存在差异。在 32 位中,我在 paging_init 函数中找到了初始化和主控内核页表的pagetable_init函数。
32 位的函数 paging_init
void __init pageit_init(void){
pagetable_init();
__flush_tlb_all();
kmap_init();
olpc_dt_build_devicetree();
sparse_memory_present_with_active_regions(MAX_NUMNODES);
sparse_init();
zone_sizes_init();
}
但是在 64 位中,我在paging_init函数中找不到内核页表相关函数。
void __init paging_init(void)
{
sparse_memory_present_with_active_regions(MAX_NUMNODES);
sparse_init();
node_clear_state(0, N_MEMORY);
if (N_MEMORY != N_NORMAL_MEMORY)
node_clear_state(0, N_NORMAL_MEMORY);
zone_sizes_init();
}
64位内核没有主内核页表吗?如果是真的,它只是通过直接映射来访问内核内存吗?
问题 1 和 2 的答案:不,一旦启用分页,CPU 指令仅使用虚拟地址,在读取或写入 RAM 之前使用 MMU 将其转换为物理地址。和宏不访问内存,它们只是在地址空间之间转换地址
__va
。__pa
在 32 位机器上,__va
只需添加0xc0000000
作为参数给出的物理地址,因为已设置映射,因此物理地址N
位于虚拟地址N+0xc0000000
。你想用 CPU 访问的地址必须有一个映射;你不能绕过MMU。因此,仅管理 128 MB 的映射是不够的。