我正在学习专业 Linux 内核架构,并且正在学习第 3 章内存管理。而我研究的时候内核地址空间本身就分为直接映射区、vmalloc区、kmap区和固定映射区。
我想知道的是就像下面这样。
32位机内核地址空间的直接映射区(896MB)可以通过__va、__pa等函数在没有MMU的情况下访问吗?
如果 1. 为 true 那么主内核页表(swapper_pg_dir)仅管理 128MB ?
当我研究内核代码时,我发现 32 位和 64 位之间的 paging_init 函数存在差异。在32位中,我发现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位中,我找不到内核页表相关的函数分页初始化功能。
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
问题 1 和 2 的答案:不,一旦启用分页,CPU 指令仅使用虚拟地址,在读取或写入 RAM 之前使用 MMU 将虚拟地址转换为物理地址。__va
和宏__pa
不访问内存,它们只是在地址空间之间转换地址。在 32 位机器上,__va
只需添加0xc0000000
作为参数给出的物理地址,因为映射已设置为物理地址N
位于虚拟地址处N+0xc0000000
。
CPU要访问的地址必须有映射;你无法绕过MMU。因此,仅管理 128 MB 的映射是不够的。