应如何设计操作系统的 API,使用户可以操作进程?核心的 API 应该有:
- 创建进程
- 销毁进程
- 等待进程退出
- 控制能力:比如暂停进程、继续进程
- 查询进程状态
对于 Linux 系统来说,创建一个新进程使用的是 fork()
;如果想在新创建的进程中运行完全不一样的 binary,使用 exec()
。
分离 fork()
exec()
的好处是,可以在 fork 后 exec 前做一些操作,比如给新进程设置环境变量、重定向文件等。比如:
wc p3.c > newfile.txt
对于这样的 shell 命令,shell 可以在 fork 后、exec wc
命令之前,在 fork 出来的子进程中打开 newfile.txt
,并将 stdout 定位到文件中。
fork 使用须知
对于带缓冲区的输出流(buffered stream),比如 stdout,在 fork 之前应该调用 fflush(stdout)
。比如下面这段代码,如果不调用 fflush
,同时 stdout 是 buffered stream(参考 OS: I/O: Stream)时,会输出 两行 Hi(unexpected):
int main() {
printf("Hi\n");
fflush(stdout);
fork();
return 0;
}