9

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

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

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

似乎当任何一个进程尝试写入页面时。页面的新副本被分配并分配给产生页面错误的进程。原始页面随后被标记为可写。

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

4

2 回答 2

12

如果fork从原始父进程多次调用,则每个子进程和父进程都将其页面标记为只读。当子进程尝试写入数据时,父进程的页面将被复制到其地址空间,并且复制的页面在子进程中被标记为可写,但在父进程中不可写。

如果fork从子进程调用并且孙子进程尝试写入,则原始父进程的页面被复制到第一个子进程,然后再到孙子进程,并且所有内容都标记为可写。

于 2012-12-11T04:47:49.977 回答
2

如果原始页面属于单个进程,则仅将其标记为可写,如果有多个分叉,则可能不是这种情况。新页面总是被标记为可写,因为它只属于试图写它的进程。

于 2012-12-11T04:42:07.583 回答