【问题标题】:If you fork() and the forked (child) process exits are all the VM pages still marked COW in the parent?如果你 fork() 和分叉(子)进程退出,所有 VM 页面在父进程中是否仍标记为 COW?
【发布时间】:2013-03-13 09:15:10
【问题描述】:

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

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

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

【问题讨论】:

  • 我不确定,但你应该使用posix_spawn,而不是fork,来运行外部程序。
  • IIRC,COW 设置在 both 父页面和子页面上。第一个得到页面错误并且页面被克隆(并且克隆的页面都没有设置COW)顺便说一句:你可以查看源代码。它是开源的,你知道...

标签: c linux fork virtual-memory


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      • 2022-11-13
      • 1970-01-01
      • 2015-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多