parent 进程在写入时复制期间是否失去写入能力?

Does parent process lose write ability during copy on write?

假设我们有一个特定的 parent 进程,内存中存储了任意数量的数据,我们使用 fork 生成一个 child 进程。据我所知,为了 OS 执行写时复制,内存中包含我们正在修改的数据的特定页面将设置其 Read-only 位,并且 OS 将使用 child 尝试修改数据以将整个页面复制到内存中的另一个区域时将导致的异常,以便 child 获得它自己的副本。我不明白的是,如果内存中的那个特定部分被标记为 Read-only,那么数据最初属于的 parent 进程也将无法修改数据。那么整个计划如何运作呢? parent 是否会失去其数据的所有权并且即使 parent 本身尝试修改数据也必须执行写时复制?

对,如果任何一个进程写了​​一个 COW 页面,它就会触发页面错误。

在页面错误处理程序中,如果页面应该可写,它会分配一个新的物理页面并执行memcpy(newpage, shared_page, pagesize),然后更新页面table 将新页面映射到该虚拟地址的任何进程的错误。然后 returns 到 user-space 存储指令到 re-run.

这是 fork 之类的胜利,因为一个进程通常会在通常接触一页(堆栈内存)后立即进行 execve 系统调用。 execve 销毁该进程的所有内存映射,有效地用新进程替换它。 父进程再次拥有每个页面的唯一副本。 (除了 已经 copy-on-write 的页面,例如分配给 mmap 的内存通常 COW-mapped 到单个零物理页面,因此读取可以命中在 L1d 缓存中)。

一个聪明的优化是 fork 实际复制包含堆栈顶部的页面,但仍然对所有其他页面执行惰性 COW,假设子进程通常会 execve 立即删除它对所有其他页面的引用。不过,暂时将所有页面翻转到 read-only 并返回,仍然需要在父级中使 TLB 失效。

Some UNIX implementations share the program text between the two since that cannot be modified. Alternatively, the child may share all of the parent’s memory, but in that case the memory is shared copy-on-write, which means that whenever either of the two wants to modify part of the memory, that chunk of memory is explicitly copied first to make sure the modification occurs in a private memory area.

Excerpted from: Modern Operating Systems (4th Edition), Tanenbaum