Skip to content

方法Method

fork的写时复制与页生命周期

Copy-on-write fork · COW fork · 写时复制进程创建

在父子私有内存语义下追踪PTE降权、引用计数、写故障复制、独占快路和退出释放,并核验分配失败不破坏旧状态。

形式陈述 ​

COW fork实现父子进程私有内存的初始相同内容:先共享物理页,把原本可写的私有映射暂时降为只读;某一方首次写时,借写故障为写者建立独立副本。逻辑可写性与硬件W位要分开保存,OS-16用软件COW标记说明“本应可写但为共享而暂时禁写”。真正只读代码保持COW=0。

本页范围限定为匿名私有页与只读代码,无共享文件页、DMA pin或页缓存持有者;每个进程对同一匿名私有页最多有一个用户映射,不允许同进程内多个VPN作为该页的私有别名。若要支持这种别名,写时须按别名组共同重定向,不能逐个PTE独立复制。ref[f]精确定义为指向数据页框f的存活用户叶PTE数量;内核访问物理内存的直接映射不计入,页表页由另一内核分配账本管理。页框可回收还要求没有正在使用它的内核操作;OS-16以不可抢占的短页管理阶段满足这一点。

fork先为子页表准备足够元数据,再对每个已映射页增加引用。原私有可写页的父子项都改W=0,COW=1,在子进程变为可运行之前完成父相关TLB失效。尚未驻留的合法区域复制区域记录,不凭空增加数据页引用。

写故障时重新核验区域可写、PTE存在且COW=1。若ref=1,可在原页恢复W并清COW,无需复制;若ref>1,先分配并复制整页,成功后把写者PTE换到新页、设W、清COW,完成翻译失效,再减旧页引用。对旧页的最后引用释放必须在旧翻译不再可用之后。

直觉

COW保存的是“写之前彼此不能影响”的语义,而非“任何写都必然复制”的机械规则。仅剩一个持有者时,已经没有另一个私有快照需要保护,恢复写权就足够。共享只读代码却不能因此变可写,因为它从来没有逻辑写权限。

refcount记录的是物理页还被谁映射,不是程序变量中有多少个相同指针。父进程把某个地址复制到十个寄存器,不会产生十个页引用;fork多一份PTE才使这里的计数增加。

例子与边界

从共享到复制,再到全部释放 ​

P有代码VPN0x10→PFN0x40、数据VPN0x12→0x30、匿名VPN0x13→0x60,三个ref均1。0x30AB为7,0x6005为1。fork产生C后,三个ref均2;0x30、0x60的两份PTE均只读COW,0x40仍只读非COW。

事件 ref[0x30] ref[0x60] ref[0x61] ref[0x40] 可观察结果
fork完成 2 2 0 2 父子都读7
C写0x12AB=8 1 2 1 2 复制0x30到0x61,C读8,P读7
P写0x12AB=11 1 2 1 2 ref=1快路,P读11,C仍读8
C解除VPN0x13 1 1 1 2 0x60仍归P,不能释放
P退出 0 0 1 1 释放0x30、0x60;C仍可运行
C退出 0 0 0 0 释放0x61、0x40

这里只发生一次256B数据复制,两次COW写故障;父的第二次写仍要改权限并失效TLB,不能因为“不复制”就跳过协议。Q独立使用的PFN0x50始终ref=1,不进入这张父子共享表。

COW引用与复制轨迹

内核写用户缓冲也要经过分离 ​

用户PTE的W=0只能挡住相应受检查的访存,不能阻止内核通过物理直接映射写同一页。OS-16因此规定:所有向用户私有缓冲写入的内核助手,都先验证区域逻辑写权限,并对COW页执行同一分离协议,然后才写入当前PTE对应页框。例如fork后C执行read(fd,0x12AB,1)接收字节8,若助手直接覆盖0x30AB,P原来的7也会变8;正确助手先使C转到独立页0x61。该路径不一定发生用户态store陷阱,却承担同样的隔离义务。

分配失败必须保持原快照 ​

若C写时没有空闲页,OS-16报告内存不足,旧PTE仍指0x30、ref仍2、内容仍7。错误做法是先把ref减到1并撤销旧PTE,再发现新页分配失败;此时C的合法旧内容已丢失,父甚至可能把唯一引用当作独占页直接写入。

fork自身也可能在复制页表元数据中途失败。实现需要先预分配,或回滚已经增加的引用及未发布子表。不能把一半建好的子地址空间投入调度。若父权限被临时降级,失败后可恢复或保留可正确处理的COW状态,但TLB与PTE必须一致。

推论与应用

不变量是:任何具有多个私有持有者的数据页,不存在能绕过COW协议的用户可写映射,内核用户拷贝助手也不绕过分离直接修改它。fork通过降权与失效建立它;多引用写分配新页使写者独立;单引用快路不再涉及共享;解除映射只减少持有者。归纳得到父子普通写互不改变对方私有字节。

若有n个已驻留页,eager fork复制nB字节;COW仍需处理页表与引用,后续m次真正分离复制至多mB字节,m依共享期间的写行为。COW改善常见fork后exec路径,却会把首写延迟推后,也可能在fork成功后才遭遇内存不足。

rev5 xv6教材把COW放在§5.3的真实系统扩展中;其基础fork仍复制用户内存。本页不是宣称原版xv6已经实现这张COW状态机,也不是数据库影子分页的持久根提交协议。

参考资料
  • Cox、Kaashoek、Morris,xv6教材 rev5,§5.3;COW作为可选实现思想及只读映射触发复制。
  • MIT 6.1810,Copy-on-Write Fork实验,页引用、原只读页与分配失败等实现义务。本文页表、地址和失败轨迹独立构造。
关系图谱6 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组