阿晨1998
使用fork和exec这体现了UNIX的精神,因为它提供了一种启动新进程的非常简单的方法。这个fork调用基本复制当前进程,在差不多了千方百计。并不是所有的东西都被复制(例如,某些实现中的资源限制),但是想法是创建尽可能接近的副本。新进程(子进程)获得不同的进程ID(PID),并将旧进程(父进程)的PID作为父进程PID(PPID)。因为这两个进程现在运行的代码完全相同,它们可以根据fork-孩子得到0,父母得到孩子的PID。当然,假设fork调用有效-如果没有,则不会创建任何子级,并且父程序将获得一个错误代码。这个execCall是一种以新程序替换整个当前进程的方法。它将程序加载到当前进程空间,并从入口点运行它。所以,fork和exec经常按顺序使用,以使一个新程序作为当前进程的子进程运行。当您尝试运行这样的程序时,shell通常会这样做。find-壳叉,然后子装载find将程序输入内存,设置所有命令行参数、标准I/O等。但它们不需要一起使用。对于一个程序来说,完全可以接受fork本身没有exec例如,如果程序同时包含父代码和子代码(您需要小心操作,每个实现可能都有限制)。这在守护进程中被大量使用(而且现在仍然如此),这些守护进程只需在TCP端口上侦听和fork当父程序返回到侦听过程中处理特定请求的自身副本。类似地,那些知道它们已经完成并且只想运行另一个程序的程序不需要fork, exec然后wait为了孩子。他们可以直接将子程序加载到他们的进程空间中。一些UNIX实现有一个优化的fork它使用的是他们所谓的抄写。这是一个延迟复制进程空间的技巧。fork直到程序试图在那个空间改变一些东西。这对于那些仅使用fork而不是exec因为他们不需要复制整个进程空间。如果exec 是调用如下fork(这是通常发生的情况),这会导致对进程空间的写入,然后对子进程进行复制。请注意,有一个完整的家庭exec电话(execl, execle, execve等等)但是exec在上下文中,意思是它们中的任何一个。下图说明了典型的fork/exec操作时,bashshell用于列出具有ls指挥:+--------+| pid=7 || ppid=4 || bash |+--------+ | | calls fork V+--------+ +--------+| pid=7 | forks | pid=22 || ppid=4 | ----------> | ppid=7 || bash | | bash |+--------+ +--------+ | | | waits for pid 22 | calls exec to run ls | V | +--------+ | | pid=22 | | | ppid=7 | | | ls | V +--------++--------+ || pid=7 | | exits| ppid=4 | <---------------+| bash |+--------+ | | continues