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