虚拟地址空间
mm_struct
管理进程的整个虚拟地址空间,记录代码段/数据段/堆/栈的边界,维护页表和 VMA。
struct mm_struct {
unsigned long start_code, end_code; // 代码段起始/结束地址
unsigned long start_data, end_data; // 数据段起始/结束地址
unsigned long start_brk, brk; // 堆的起始/当前边界
unsigned long start_stack; // 栈的起始地址
unsigned long arg_start, arg_end; // 命令行参数地址范围
unsigned long env_start, env_end; // 环境变量地址范围
pgd_t *pgd; // 页目录表指针
struct vm_area_struct *mmap; // 虚拟内存区域链表头
// ...
};
vm_area_struct
细化虚拟内存区域(如权限、文件映射),通过链表/红黑树组织
struct vm_area_struct {
unsigned long vm_start; // 区域起始地址
unsigned long vm_end; // 区域结束地址
struct mm_struct *vm_mm; // 所属的 mm_struct
unsigned long vm_flags; //访问权限
struct file *vm_file; // 映射的文件(如果有)
struct vm_area_struct *vm_next; // 链表下一个 VMA
// ...
};
fork()
时的页表管理
-
父子进程共享物理页
fork()
创建的子进程会复制父进程的 页表,同一虚拟地址映射相同物理页- 内核会同时降级父进程和子进程的页表权限,将它们都标记为只读(Read-Only),以实现写时拷贝(COW)
-
写入时触发缺页异常
- 当父进程或子进程尝试写入共享页时,CPU 检测到页表权限不足(只读页被写入),触发 缺页异常(Page Fault)。
- 异常中断函数发现这是 COW 页,于是:
- 分配新物理页,复制原页内容。
- 更新当前进程的页表,使其指向新页,并恢复可写权限。
- 另一进程仍指向旧页。