- 涉及三块内容:
- 内存映射函数 vmalloc, kmap_atomic
- 内核态页表存放位置和工作流程
- 内核态缺页异常处理
- 内核态页表, 系统初始化时就创建
- swapper_pg_dir 指向内核顶级页目录 pgd
- xxx_ident/kernel/fixmap_pgt 分别是直接映射/内核代码/固定映射的 xxx 级页表目录
- 创建内核态页表
- swapper_pg_dir 指向 init_top_pgt, 是 ELF 文件的全局变量, 因此再内存管理初始化之间就存在
- init_top_pgt 先初始化了三项
- 第一项指向 level3_ident_pgt (内核代码段的某个虚拟地址) 减去 __START_KERNEL_MAP (内核代码起始虚拟地址) 得到实际物理地址
- 第二项也是指向 level3_ident_pgt
- 第三项指向 level3_kernel_pgt 内核代码区
- 初始化各页表项, 指向下一集目录
- 页表覆盖范围较小, 内核代码 512MB, 直接映射区 1GB
- 内核态也定义 mm_struct 指向 swapper_pg_dir
- 初始化内核态页表, start_kernel→ setup_arch
- load_cr3(swapper_pg_dir) 并刷新 TLB
- 调用 init_mem_mapping→kernel_physical_mapping_init, 用 __va 将物理地址映射到虚拟地址, 再创建映射页表项
- CPU 在保护模式下访问虚拟地址都必须通过 cr3, 系统只能照做
- 在 load_cr3 之前, 通过 early_top_pgt 完成映射
- vmalloc 和 kmap_atomic
- 内核的虚拟地址空间 vmalloc 区域用于映射
- kmap_atomic 临时映射
- 32 位, 调用 set_pte 通过内核页表临时映射
- 64 位, 调用 page_address→lowmem_page_address 进行映射
- 内核态缺页异常
- kmap_atomic 直接创建页表进行映射
- vmalloc 只分配内核虚拟地址, 访问时触发缺页中断, 调用 do_page_fault→vmalloc_fault 用于关联内核页表项
- kmem_cache 和 kmalloc 用于保存内核数据结构, 不会被换出; 而内核 vmalloc 会被换出
展开