创建进程的两种方式
- 在shell中执行命令或者可执行文件,此时由shell进程调用fork函数创建子进程
- 在代码中调用fork函数创建子进程
PID为0的进程和init进程
PID=0的进程创建init进程之后,便成了空闲进程,而init进程是所有进程的父进程,init进程的PID=1。
创建子进程
pid_t fork(void)
fork
函数被正确调用之后,将会在子进程和父进程中分别返回;在子进程中返回0(不合法的PID);在父进程中返回子进程PID,出错则返回-1。
根据fork返回值的不同,可以判断当前是在子进程中运行代码还是在父进程中运行代码。
如下示例:
父子进程的异同点
父子进程共享文件
- 父子进程文件共享的处理方式:
- 父进程等待子进程文件处理完毕;
- 父子进程分别执行不同的代码段,关闭不需要的文件;
- 父进程希望复制自己(共享代码,复制数据空间),但父子进程执行相同代码中的不同分支。
比如网络服务:
父进程等待客户端的服务请求,当请求到达时,父进程调用fork创建子进程处理请求,而父进程继续等待下一个服务请求的到达。 - 父子进程执行不同的可执行文件(父子进程具有完全不同的代码段和数据段)
子进程通过fork返回以后,立即调用exec类函数执行另一个可执行文件(可以参考exec函数的相关博客)。
vfork函数
- 创建新进程,执行另一个可执行文件
- 新程序拥有自己的地址空间,vfork函数并不完全把父进程的地址空间复制到子进程中
- 子进程在调用exec或者exit之前,在父进程的地址空间运行
- 子进程先执行,父进程才会被调度执行(父进程处于TASK_UNINTERRUPTIBLE状态)