7

在 Linux 上,如果你 fork() 和分叉的(子)进程退出,所有虚拟内存页面在父进程中是否仍标记为写时复制?

我认为这些页面将保持标记为 COW,因为其他任何东西实施起来可能会非常昂贵,可能需要每页的引用计数和其他昂贵的簿记。但是前几天我想知道,如果我分叉一个进程以在当前进程的“稳定快照”中执行一些代码。当子进程退出时会发生什么?父级中的所有内存页是否都标记为写时复制?这意味着在具有大量虚拟内存(例如 128GB+)的进程中分叉仅执行一些代码几分钟会导致父进程在数小时甚至数天后挥之不去的性能下降(更不用说 fork 调用本身)这不会便宜。)

我只是好奇 Linux 上的实际行为是什么(我不知道如何测试它。)

4

2 回答 2

9

除了写时复制位之外,页表中还有一个引用计数。所以当一个child fork时,parentent中的所有非私有页面都被标记为COW,并且引用计数增加。

然后当子进程运行时,父进程写入一个页面,它会出现页面错误,并且页面被复制,就像你期望的那样,并且引用计数减少了。当子进程退出时,它会将所有页面引用减一,引用计数为零的页面将被丢弃。

现在,当父级写入一个设置了 COW 位且引用计数为 1 的页面时,COW 位将被简单地忽略。

于 2013-03-23T16:11:47.447 回答
0

内核将所有共享页面标记为写保护,因此如果其中任何一个尝试修改一个,都会导致异常。副本被创建,并被标记为可写(因此不再有例外),而原件保持写保护。

如果写入原始页面,则会发生另一个异常,但内核将看到该页面未被任何其他进程共享,因此也会将该页面标记为可写。当一个进程终止时,它的所有页面都被释放,因此内核将在父进程中的每个页面被修改时有效地删除 COW 状态。

于 2013-03-23T16:51:36.347 回答