c - 进程 fork 后会发生什么?

标签 c linux gcc fork x86-64

假设一个进程是从另一个进程派生出来的。也就是说,我们通过fork函数调用来复制一个进程。现在由于 fork 是一种写时复制机制,发生的情况是每当 fork 进程或原始进程写入页面时,它们都会获得一个新的物理页面来写入。所以据我了解,当 fork 进程和原始进程都在执行时,事情就是这样。

--> fork 时,原始进程和 fork 进程的所有页面都被授予只读访问权限,以便内核知道写入了哪个页面。当发生这种情况时,内核将一个新的物理页面映射到写入进程,将之前的内容写入其中,然后授予对该页面的写入权限。现在我不清楚的是,如果 fork 进程和原始进程都写入同一页,它们中的一个是否仍会保留原始物理页面(在 fork 之前),或者两者都会获得新的物理页面。其次,我的假设是否正确,即 fork 和原始进程中的所有页面在 fork 时都被授予只读访问权限?

--> 现在由于每个页面错误都会触发一个中断,这意味着每次写入原始或 fork 进程都会减慢执行速度。假设我们了解该应用程序,并且我们知道将写入大量连续的内存页面,那么当组中的一个页面时,授予对多个页面(可以说是一组页面)的写权限不是更好吗被写入。这将减少由于页面错误处理而导致的中断次数。不是吗?当然,在这种情况下我们有时可能会进行不必要的复制,但我认为中断比写入 512 个 long 类型的变量(一页的 4096 字节)的开销要大得多。我的理解正确还是我遗漏了什么?

最佳答案

如果我没记错的话,其中一个进程将被视为首先写入页面。即使你有多个内核,我相信页面错误也会被串行处理。在那种情况下,第一个被捕获的将分离两个进程的页面,所以当第二个写入它时,不会有错误,因为它现在有一个可写的页面拥有。

我相信完成后,现有页面将由一个进程保留(并设置回读/写),并为另一个进程制作一个新副本。

我认为您的第三点围绕一个简单的要点:“如果我们知道该应用程序......”。这就是问题所在:操作系统知道该应用程序。本质上,它“知道”的唯一事情将是间接的,通过内核编码人员的观察。他们无疑会观察到 fork 通常后跟 exec,因此他们无疑会针对这种情况进行优化。是的,情况并非总是如此,您显然很关心其他情况——我在这里要说的是,它们非常不寻常,我猜想在它们身上花费的精力很少。

我不太确定我是否遵循了 4096 字节页面中 512 长整型的逻辑或数学 -- 第一次页面被写入时,它在进程之间被复制和解耦。从那时起,进一步写入该页面的任何一个进程的副本都不会导致任何进一步的页面错误(至少与写入时的副本有关——当然,如果一个进程站点长时间空闲,则数据可能会被调出到页面文件,或该命令中的其他内容,但在这里无关紧要)。

关于c - 进程 fork 后会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10217127/

相关文章:

c - 'make' 等同于 gcc 中的 -D 标志

c - 如何解决 C : 'can' t find a register in class 'GENERAL_REGS' while reloading 'asm' ' 中的内联汇编错误

c - 如何为 char* 释放内存

c - 将 linux.words (/usr/share/dict/words) 中的前 10 个单词写入数组

linux - 在 bash 中按整数序号发出字符(或多字节二进制字符串)

c - 使用 C11 和 GNU11 编译器标志的机器 epsilon 计算是不同的

c++ - 自己构建GCC后如何配置共享库搜索路径?

c - 从 C 中的字符串中读取数据(如 scanf)

c - 在C中将四个字节解析为 float

c - 用于跟踪的系统库?