Linux X86架构下程序启动阶段用户进程页表首次更新的时机与位置
问题1:推测正确性验证
你的推测完全正确。
Linux采用*按需调页(Demand Paging)*机制,在do_execve启动程序的全流程中,仅完成虚拟内存布局的搭建,不会提前为用户态虚拟地址分配物理内存、填充页表项:
- 你提到的
do_execve创建mm_struct和顶层pgd的阶段,pgd仅会复制内核空间的全局页表项,用户态对应的页表条目全部为空 elf_map调用do_mmap的阶段,仅会创建对应的vm_area_struct(虚拟内存区域描述符)插入进程的虚拟地址空间,不会操作各级用户态页表START_THREAD启动进程时,用户态所有虚拟地址对应的页表均未填充,首次访问时会触发缺页异常,由内核完成页表的更新、物理内存的分配操作
问题2:X86架构下首次更新页表的代码路径
首次页表更新完全在缺页异常处理流程中完成,核心代码位置如下:
- 缺页异常架构层入口:
arch/x86/mm/fault.c中的do_page_fault()函数,负责解析缺页地址、缺页原因,过滤非法地址后调用通用缺页处理逻辑 - 通用缺页处理核心:
mm/memory.c中的handle_mm_fault()函数,根据缺页地址对应的vma属性,分配不同的处理分支:- 若为ELF段这类文件映射缺页,走
do_fault()分支,读取文件内容到新分配的物理页后,完成页表填充 - 若为栈、堆这类匿名映射缺页,走
do_anonymous_page()分支,分配空白物理页后完成页表填充
- 若为ELF段这类文件映射缺页,走
- 实际写入页表项的底层接口:上述分支最终都会调用
set_pte_at()函数完成页表项的写入,这就是页表首次更新的最终执行点,X86架构下该函数会直接操作对应页表的物理内存,完成后刷新TLB即可让用户态正常访问对应虚拟地址。
内容的提问来源于stack exchange,提问作者Luba A
相关产品推荐
相关产品推荐

