raj*_*raj 43
fork()创建一个新进程,它是父进程的副本。因此,如果您仅执行此操作fork(),则会运行两个相同的进程。因此,为了用另一个代码替换分叉进程,您需要执行exec()用指定的可执行文件替换当前正在运行的进程的操作。
Linux 内核就是这样组织的。您没有一个系统调用可以同时创建新进程并加载新的可执行文件。您必须分两步完成 - 首先创建新进程,然后将新的可执行文件加载到该新进程中。(尽管您的编程语言中可能有一个结合了这两者的库函数- 例如spawn()在许多 C 变体中都有)。
有时exec()不需要,如果您只需要创建当前进程的另一个副本即可。例如,许多守护进程都会这样做。
dav*_*bak 33
这是因为历史原因:太初只有fork和exec。因为它很容易实现(根据 DMR:只有 27 行 PDP-7 汇编代码fork! - 参见路上的Afork() (Baumann, Appavoo, Krieger, Roscoe, 2019) - 次要来源,尽管它引用了主要来源来源The Evolution of the Unix time-sharing system (Ritchie, 1979). 不管怎样,真正的从头开始直接进程创建是后来才出现的。(可能不在 POSIX 中?)
事实上,真正的直接进程创建 API 的出现要晚得多,这一事实至今仍影响着 Unix 编程。因为数百本书籍、手册、教程、幻灯片和课程都是为了解释而编写的,fork并且exec几十年来它们一直被教授给学生和程序员,作为在Unix 中进行进程创建/控制的方法,并且广泛的遗产在代码方式中持续存在写到今天。
哦,这是《Unix 分时系统的演变》(Ritchie,1979)。向下滚动到第 6 页可以看到:“现代形式的流程控制是在几天内设计和实现的。......事实上,PDP-7 的fork调用精确地需要 27 行汇编代码。”
use*_*198 13
因为 exec 不会创建进程,并且 linux 没有用于创建进程和加载可执行文件的单个系统调用,因为这只适用于使用没有预先存在的资源的新可执行文件创建进程的简单情况。如果您想做的不仅仅是琐碎的事情,复杂性会迅速增加,并且更容易拥有单独的“创建进程”和“启动可执行文件”步骤,并且能够在两者之间操纵进程。有关于此的讨论,请参阅https://lwn.net/Articles/360556/ 。
Unix,回到最早的版本已经解决了这个问题,方法是使用 fork 创建父进程的副本,专用于设置环境,然后在完成后加载新的可执行文件。然后,子进程处于一种临时状态,可以访问父进程的所有资源,但在子进程中运行。这种方法有几个优点:
与大多数“分叉羞辱”现有答案略有不同的观点......;)
最初,正如 @davidbak 提到的,这样做可能非常简单。但是,在多次使用fork/进行工作(并且经常使用 only进行多处理)之后,这种工作方式仍然存在且活跃,并且没有被委托给历史的迷雾,这肯定是有原因的:execfork
fork并将其作为语言的一部分提供。因此,每种语言都有一个相对简单的(与进程内多线程相比)方法来至少为其用户提供多处理。(注意:一个例外是,如果您在程序中使用多线程 -在分叉之后,只有一个线程在运行;除了最微不足道的多线程应用程序之外,这可能会导致所有明显的问题。)fork,就不再需要学习有关新环境的更多信息 - 它总是像任何其他语言一样简单。exec。它允许我们用不同的东西替换当前的进程映像(即正在执行的可执行文件)。比如说,让一些脚本或程序准备某种环境,然后执行其他东西,同时从场景中消失,这就变得很干净。它不仅释放资源(RAM,还释放进程表中的空间等),而且让任何参与或查看它的人都非常清楚,以前的父进程在未来将不再扮演任何角色。您经常在编写良好的bash脚本中发现这一点,这些脚本在启动“有效负载”时释放bash解释器的资源。此外:
fork但让+exec相互跟随仍然很容易。除非您需要,否则您不必在中间做很多事情(或者根本不需要做任何事情)。fork+exec. 请注意,在这里我们看到复杂性已经露出了丑陋的头;Linux 还有一个clone3函数,它可以取代clone并使界面变得更简单或更方便(使用structs而不是那么多标志)。| 归档时间: |
|
| 查看次数: |
9626 次 |
| 最近记录: |