从零写OS(十八):fork 与 Copy-on-Write

上一章每个进程有了自己的地址空间。这一章实现 fork()——创建一个子进程,继承父进程的全部内存。 最朴素的 fork 实现 fork 的语义是"完整复制当前进程"。最直接的做法:遍历父进程页表,找到每一个物理页,分配新页,复制 4096 字节内容,给子进程建新映射。 能用,但很浪费。大多数 fork() 之后会紧接着 exec()——旧内存根本用不上,全拷了白拷。进程堆如果有几十 MB,每次 fork 都要等好几毫秒。 Copy-on-Write:先共享,写了再分 CoW 的思路是:fork 时不复制,让父子共享同一批物理页;等到谁要写,再给他一份新的。 实现上分两步: 第一步:fork 时打标记 遍历父进程用户页表,对每一页做两件事: 清掉 WRITABLE 位,变成只读 打上 PAGE_COW 标志(借用 x86 页表的 bit 9,这一位 CPU 不使用,留给软件自定义) 子进程页表复制同一个物理页地址,同样只读 + CoW。 fork 后: 父进程 → PT → 物理页 0xA000 (只读, CoW) ↑ 共享 子进程 → PT → 物理页 0xA000 (只读, CoW) 注意一个关键细节:PDPT/PD/PT 这三级结构页必须为子进程单独分配。如果父子共用同一棵结构树,后续 vmm_map_page 修改子进程时会把父进程的 PT 一起改掉,隔离失效。数据页可以共享,结构页不能。 另一个细节:改完父进程页表后必须刷新 TLB。否则 CPU 缓存里还是旧的可写映射,父进程写该页不会触发 fault,CoW 形同虚设。 ...

May 8, 2026 · 2 min · 大飞
京ICP备14031575号-3