一、fork函数
1、每个进程都有一个非负整数表示的唯一进程ID,进程ID是可复用的;
- ID为0的进程通常是调度进程,被称为交换进程(swapper),属于内核的一部分,并不执行任何磁盘上的程序,也被成为系统进程;
- ID为1的进程通常是init进程,init通常读取与系统有关的初始化文件。init进程绝不会终止,他是一个普通的用户进程,但是可以超级用户特权运行。
- ID为2的是页守护进程,负责支持虚拟存储器系统的分页操作。
2、一个现有的进程可以调用fork函数创建一个新进程。
#include <unistd.h>
pid_t fork(void);
//返回值:子进程返回0,父进程返回子进程ID,若出错,则返回-1;
由fork创建的新进程被称为子进程(child process),fork函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值是新建子进程的进程ID。
- fork使子进程得到返回值0,理由:
一个进程只会有一个父进程,所以子进程总是可以调用getppid以获得其父进程的进程ID(进程ID0总是由内核交换进程使用,所以一个子进程的进程ID不可能为0)。
- 子进程ID为什么要返回给父进程?
一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程ID。
经过GCC之后,
可以看出子进程的变量值改变,子进程ID是9111,父进程ID为9110.
3、fork的两种用法
(1)一个父进程希望复制自己,使父进程和子进程同时执行不同的代码段。
比如在网络服务进程中,父进程等待客户端的服务请求,当这种请求到达时,父进程调用fork,使子进程处理此请求,父进程则继续等待下一个服务请求。
(2)一个进程要执行不同的程序
shell中常见,子进程调用fork返回后立即调用exec。
二、vfork函数
vfork函数用于创建一个新进程,而该新进程的目的是exec一个新程序。
vfork与fork都是创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec或者exit,于是也就不会引用该地址空间,不过在子进程调用exec或exit之前,他在父进程的空间中运行。
vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行,当子进程调用这两个函数中的任意一个时,父进程会恢复运行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁)。
参考《UNIX环境高级编程》第三版。