为什么fork和exec保持2个单独的调用

lon*_*ger 11 unix kernel fork process

我理解fork,vfork,exec,execv,execp之间的区别.所以请不要咆哮.我的问题是关于unix进程创建的设计.为什么设计师会想到创建两个单独的调用(fork和exec)而不是保持一个紧密的调用(spawn).良好的API设计是一个原因,以便开发人员能够更好地控制流程创建吗?是因为性能原因,我们可以延迟为子进程分配进程表和其他内核结构,直到写入时复制或访问时复制?

caf*_*caf 7

主要原因可能是fork()和/和exec()步骤的分离允许使用其他系统调用来完成子环境的任意设置.例如,您可以:

  • 设置一组任意打开的文件描述符;
  • 改变信号掩码;
  • 设置当前工作目录;
  • 设置进程组和/或会话;
  • 设置用户,组和补充组;
  • 设置硬资源和软资源限制;

......还有更多.如果要将这些调用组合到一个spawn()调用中,则必须具有非常复杂的接口,以便能够对子环境中所有这些可能的更改进行编码 - 如果您添加了新设置,则需要接口要改变.在另一方面,独立fork()exec()步骤,使您可以使用普通的系统调用(open(),close(),dup(),fcntl(),...)来操纵孩子的环境之前exec().capset()很容易支持新功能(例如).

  • 但还必须基本上接受每个系统调用,并实现一个可以应用于此类流程对象的版本。这相当于为每个系统调用提供了一个额外的参数“process_object_to_be_affected”。默认的 UNIX 系统调用是简并形式,“self”作为“process_object_to_be_affected”。 (2认同)

Eri*_*rik 4

fork 和 exec 做完全不同的事情。

  • fork() -复制一个进程
  • exec() -替换进程

有很多理由只使用其中之一而不使用另一个。您可以派生代表您的控制父应用程序执行任务的子进程,例如,这在 UNIX 世界中很常见。例如,您可以为其他一些奇怪的应用程序设置先决条件,然后从启动器应用程序中执行它,而无需使用 fork。

  • 难道不是说“spawn”系统调用可以比“fork + exec”更有效地实现吗?对我来说,“spawn”不需要像 fork 那样复制数据段。 (3认同)
  • 或者更常见地使用普通的“exec”,重新启动您的应用程序(例如,如果网络守护进程检测到二进制文件的新版本并且处于空闲状态,则会执行此操作)。 (2认同)