0%

为什么Linux下创建进程分为fork和exec两个函数?

在学习Linux的时候,应该也要思考为什么API是这样的,这样设计的目的/历史原因是什么?要如何设计一个功能强大,容易使用,较高性能的接口?

在重读Operating Systems: Three Easy Pieces的时候看到了这个问题的解答。
在第五章Process API的第5.4中Why?Motivating The API作者做了一些解释。

UNIX通过一对system calls: fork()exec()(一组函数)来创建新进程。另外可以使用wait()来进行进程等待。

其中fork()用于创建一个新进程。wait()用于parent进程等待child结束。exec*用来让子进程执行另一个命令。

回到问题,就是为什么要用两个函数fork()exec()来完成创建新进程这件事?

原因在于这样的设计可以让shellfork()的后面,exec()的前面调用一些代码,特别对于UNIX中重要的shell,它可以利用这部分代码可以用来改变子进程的环境(env)等。
基本的流程:

  1. shell等待用户输入
  2. 用户输入某个command+参数
  3. shell 从 filesystem上找到这个command
  4. 通过调用fork创建子进程
  5. 调用exec*去执行命令
  6. 通过wait等待子进程结束(输出结果)
  7. 重复步骤1

通过分离fork()exec()的好处是可以在4)和5)之间允许shell进行额外的操作,实现诸如pipeline的功能。 例如下面这个命令:

prompt> wc p3.c > newfile.txt

fork之后, 执行wc这个命令之前,先关闭了stdout, 然后打开newfile.txt。在这之后wc的输出就会到newfile.txt中了。(在shell中是应该是用了pipe)