在Linux上,如果fork()和分叉(子)进程退出,那么所有的虚拟内存页面仍然在父文件中被标记为copy-on-write?
我认为这些页面将保持标记为COW,否则任何其他操作可能会非常昂贵,可能需要每页参考计数和其他昂贵的簿记。 但是我有一天在想,如果我分叉一个进程来执行当前进程的“稳定快照”中的一些代码。 subprocess退出时会发生什么? 是否将父级保留中的所有内存页标记为写入时复制? 这意味着,在一个拥有大量虚拟内存的进程(如128GB +)中,如果只执行一些代码几分钟,会导致父进程中的性能下降,几个小时甚至几天之后(更不用说叉子本身这将不便宜。)
我只是好奇在Linux上的实际行为(我不知道如何testing它)。
除了写入时复制位之外,页表中还有一个引用计数。 所以当孩子分叉时,所有非私人页面标记为COW,引用计数递增。
然后,当子进程正在运行,并且父进程写入一个页面时,将会出现页错误,并且页面像您期望的那样被复制,并且引用计数被减少。 当孩子退出时,它将减少其所有的页面引用,而引用计数为零的页面则被丢弃。
现在,当父母写入COW位已设置且引用计数为1的页面时,简单地忽略COW位。
内核将所有共享页面标记为写保护,从而在尝试修改一个时导致异常。 副本被创建,并被标记为可写(因此没有更多的例外),而原始保持写保护。
如果写入原始文件,则会发生另一个异常,但是内核将看到该页面不被任何其他进程共享,因此也会将该文件标记为可写。 当一个进程终止时,所有的页面都被释放,所以当内核被修改时,内核将有效地从父进程中的每个页面中删除COW状态。