我理解fork,vfork,exec,execv,execp之间的区别。所以请不要咆哮。 我的问题是关于unix进程创建的设计。为什么设计师会想到创建两个单独的调用(fork和exec)而不是保持一个紧密的调用(spawn)。 良好的API设计是一个原因,以便开发人员能够更好地控制流程创建吗? 是因为性能原因,我们可以延迟为子进程分配进程表和其他内核结构,直到写入时复制或访问时复制?
答案 0 :(得分:7)
主要原因可能是fork()
和exec()
步骤的分离允许使用其他系统调用来完成子环境的任意设置。例如,您可以:
......还有更多。如果您要将这些调用合并到一个spawn()
调用中,则必须具有非常复杂的接口,以便能够对子环境中所有这些可能的更改进行编码 - 以及是否添加了新设置,界面需要改变。另一方面,单独的fork()
和exec()
步骤允许您使用普通系统调用(open()
,close()
,dup()
,fcntl()
,...)在exec()
之前操纵孩子的环境。
capset()
)
答案 1 :(得分:4)
fork和exec做了完全不同的事情。
有很多理由不使用另一个。您可以代表您的控制父应用程序分叉执行任务的子进程,例如,在unix世界中非常常见。你可以,例如为其他一些古怪的应用程序设置前置条件,然后从你的启动器应用程序执行它而不使用fork。
答案 2 :(得分:0)
AFAIK,最初只有fork()。但性能原因要求创建exec(),它不会重新创建将被立即覆盖的内核结构。< - 这是错误的。
当进程需要创建一个不是自身副本的子进程时,会出现性能问题。 fork()复制与进程相关的内核数据,这些数据将立即被exec()替换。因此引入了vfork(),它不会复制过多的内核数据和任何过程数据;在它之后,一个进程应该调用exec()之类的东西,并且父进程被暂停,直到子进程为止。但是,请参阅“错误”部分以了解vfork()问题的描述。
答案 3 :(得分:0)
摘自本书草案xv6 a simple, Unix-like teaching operating system用于MIT课程6.828:
现在应该清楚为什么将fork和exec分开调用是一个好主意。因为如果它们是分开的,则外壳程序可以派生一个孩子,在孩子中使用open,close,dup来更改标准输入和输出文件描述符,然后执行。无需更改正在执行的程序(在我们的示例中为cat)。如果将fork和exec组合到单个系统调用中,则外壳将需要一些其他(可能更复杂)的方案来重定向标准输入和输出,否则程序本身将必须了解如何重定向I / O。>
基本上如caf所述,但提供了很好的参考。实现一个简单的外壳可能会使原因很清楚。
答案 4 :(得分:-2)
fork()只能用于创建子进程。只能完成父进程的复制。 而exec()可用于启动系统上的任何新进程。 我认为两者之间没有相关性。