一、进程的产生(fork)
fork(2) 系统调用会复制调用进程来创建一个子进程,在父进程中 fork 返回子进程的 pid,在子进程中返回 0。
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
fork 后子进程不继承未决信号和文件锁,资源利用量清 0。 由于进程文件描述符表也继承下来的,所以可以看到父子进程的输入输出指向都是一样的,这个特性可以用于实现基本的父子进程通信。
init() 是所有进程的祖先进程,pid = 1。
例子(fork_test.c) :
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
printf("Begin\n");
//fflush(); //!!!重要
if ((pid = fork()) == 0) {
// child
printf("child process executed\n");
exit(0);
} else if (pid < 0) {
perror("fork");
exit(1);
}
// father
//sleep(1);
printf("parent process executed\n");
exit(0);
}
运行结果:
注意:父子进程的运行顺序不能确定,由调度器的调度策略决定。
面试题:当将输出重定向到文件里面时,Begin 为什么打印了两次?如下图:
答案:输出到终端默认是行缓冲模式,加 “\n” 即可刷新缓冲区,但由于重定向到文件是写文件,而写文件是全缓冲,所以 “\n” 无法刷新缓冲区,所以需要在 Begin 后加上 fflush() 来强制刷新缓冲区。
例子(primes_fork.c,通过子进程来计算质数):
#include <stdio.h>
#includ