fork()中的写时复制如何处理多个fork?


23

根据维基百科(可能是错误的)

发出fork()系统调用时,将创建与父进程对应的所有页面的副本,并由OS加载到子进程的单独内存位置。但这在某些情况下是不需要的。请考虑以下情况:孩子执行exec系统调用(用于从C程序中执行任何可执行文件)或在以后很快退出fork()。当仅需要子进程来执行父进程的命令时,就不需要复制父进程的页面,因为exec用要执行的命令替换了调用它的进程的地址空间。

在这种情况下,将使用一种称为写时复制(COW)的技术。使用此技术时,发生派生时,不会为子进程复制父进程的页面。而是在子进程和父进程之间共享页面。每当进程(父级或子级)修改页面时,都会为执行修改的那个进程(父级或子级)单独制作该页面的单独副本。然后,此过程将使用新复制的页面,而不是将来所有引用中的共享页面。另一个过程(未修改共享页面的过程)继续使用页面的原始副本(现在不再共享)。此技术称为写时复制,因为在某些进程向页面写入内容时会对其进行复制。

似乎当任何一个进程试图将其写入页面时,都会分配该页面的新副本并将其分配给产生页面错误的进程。之后原始页面将被标记为可写。

我的问题是:如果fork()在任何进程尝试写入共享页面之前多次调用gets ,会发生什么?


在这种情况下,维基百科是正确的,只是更高层次的。
Didi Kohen

1
是的,写时复制是延迟复制,子进程在尝试写入页面时会复制该页面。因此,基本上,在分叉之后,几乎孩子的记忆与父母共享。但是,在进行任何进程之前,每个子进程仍具有一些私有内存,这些私有内存可以通过父分配或新分配进行修改。这意味着即使没有任何动作,分叉的子进程也具有一些私有内存。我们可以使用pmap -XX PID或进行验证cat /proc/PID/smap
where23 '29

关于-“原始页面之后被标记为可写。”,谁将拥有它?这里的其他进程谁还没有尝试写过呢?
阿迪尔

好可爱 让我们开始在幼儿园教书
ed22

Answers:


18

没什么特别的。所有进程共享同一组页面,并且每个进程在想要修改页面时都会获得自己的私有副本。


对。关键是,特殊的子进程在尝试写入共享页面时具有复制的工作。如果更改正确,则父母和其他孩子都不需要知道更改。
查尔斯·斯图尔特

9
子进程不是那么特别。分支之后,子进程和父进程都具有相同的一组页面只读。就这些页面而言,页面处理是对称的。
jlliagre 2012年

3

fork()的行为取决于* nix系统是否具有MMU。在非MMU系统(例如早期的PDP-11)上,fork()系统调用为每个孩子复制了父母所有的内存。在基于MMU的* nix系统上,内核将所有非堆栈页面标记为R / O,并在父级和子级之间共享它们。然后,当任一进程写入任何页面时,MMU都会捕获该尝试,内核然后分配一个可写页面并更新MMU页面表以指向现在可写的页面。这种写时复制行为可以提高速度,因为最初只需要为每个子进程分配和克隆一个私有堆栈。

如果您在每个fork()调用之间执行一些父代码,则子进程的结果将因父页面已更改的页面而异。另一方面,如果父级简单地发出多个fork()调用(例如在循环中),则子级进程几乎是相同的。如果使用局部循环变量,则在每个子堆栈中该变量将有所不同。


0

当系统执行分支时,通常(这可能取决于实现方式)通常还将页面标记为只读,并将父进程标记为这些页面的主节点。
尝试写入这些页面时,将发生页面错误,操作系统将接管,复制整个页面列表或仅复制页面列表(同样取决于实现),因此写入过程将具有可写副本。
当同一进程派生了多个进程时,当“主”进程写入其内存时,其他进程将复制其等效页。


这是哪个系统?linux使用写时复制实现
brauliobo 2014年

这就是写时复制的工作方式……
Didi Kohen 2014年

3
@DavidKohen这不是我所听说过的任何版本的写时复制功能。没有“主”过程。如果单个进程写入共享页面,则其副本将被撞到私有页面,而所有其他进程继续共享它。
Celada 2014年

1
我认为大卫·科恩(David Kohen)在某种程度上是正确的。这是实现写时复制的一种方法。要点是,使用此标记,写入该页面将触发页面错误处理程序,然后该页面处理程序将采取适当的操作,即写时复制。不幸的是,这个细节(将是特定于系统的)对于这个问题几乎是无关紧要的。请记住,CoW具有两个维度:一个对进程可见,另一个与内核如何实现它有关。
0xC0000022L15年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.