大型Unix C应用程序中分叉进程的持续时间和范围

大型Unix C应用程序中分叉进程的持续时间和范围,c,unix,process,fork,C,Unix,Process,Fork,我们在学校的Unix系统上处理C代码,我们希望通过分叉进程将应用程序拆分为几个进程。寻找有关叉子工作原理的概念性帮助 例如,我知道当您使用fork()时,会创建一个新的[child]进程,其内存空间与父进程相同(除了共享内存)。在这种情况下,“父进程”是什么?在操作系统将应用程序拆分为更小的进程之前,有多少代码基础被打包到给定的进程中?还是我对“过程”的想法都错了 例如,如果您有一个100000行的程序,在第70000行的某个地方有一个fork()调用,那么在应用程序运行时构建的整个程序和内存是

我们在学校的Unix系统上处理C代码,我们希望通过分叉进程将应用程序拆分为几个进程。寻找有关叉子工作原理的概念性帮助

例如,我知道当您使用fork()时,会创建一个新的[child]进程,其内存空间与父进程相同(除了共享内存)。在这种情况下,“父进程”是什么?在操作系统将应用程序拆分为更小的进程之前,有多少代码基础被打包到给定的进程中?还是我对“过程”的想法都错了

例如,如果您有一个100000行的程序,在第70000行的某个地方有一个fork()调用,那么在应用程序运行时构建的整个程序和内存是否都会复制,即使只有一小部分父级数据是子级成功所必需的?像这样的大型程序是否可以拆分成更小的进程来减轻fork()调用的重复负载?如果是的话,分裂在哪里?如果没有,您如何对此进行优化?应用程序一开始不应该这么大吗

类似的问题是,当创建与父进程相同的子进程时,可以假定它何时终止?使用上面100000行程序的示例,如果第100行有一个fork,那么fork子级是否会运行程序其余部分的全部,即使不需要?你如何避免这种情况?有没有我们班没有深入研究的设计因素?我们生活在一个学术代码库中,我们所有的程序都不超过50行,但我正在努力学习宏观概念,以供启发


谢谢

您对
fork()
的理解完全正确-它应该精确复制调用过程,有效地将程序的内存需求增加一倍

在实践中(明智地使用时),在大多数现代操作系统的虚拟内存实现的帮助下,大多数开销都被优化了:首先,OS只考虑可写段的拷贝(文本段——您的代码在大多数操作段上不被写入),因此这两个进程将共享相同的代码段。对于剩余的数据段,操作系统将在写入时进行复制,因此数据段只有在子级首次尝试写入时才会被复制


数据段的拷贝将逐页进行,因此,通过将父数据和子数据“不太聪明的混合”分散在页面上,您仍然可以强制将大部分未使用的父数据复制到子数据的内存空间中。使用经典的
fork()
-
exec()
对,大部分数据将被有效分离。

谢谢!在我看来,在初始化很多变量之前,尽早使用fork()是非常重要的。以这种方式拆分程序,那么您可以让单个子进程只通过代码其余部分的必要路径,以最小化不必要的内存复制。这有意义吗?呃,没有。尽早使用
fork()
不会有多大帮助,因为复制的数量主要取决于孩子。使用经典的
fork()exec()
对,它将有助于尽早执行
exec()
以避免复制数据页。如果您不执行
exec()
,它可能有助于模块化您的程序并将父数据和子数据分开(在您的程序内以及在链接器命令行上)。这将增加父数据和子数据在运行时出现在单独内存页上的可能性。当然,结果将取决于您的操作系统规格(页面大小)。