前言
fork,在英语用译为叉子,形状像Y,这实在很形象。本来运行的一个app,调用fork()函数后就产生了子进程,而原来的进程称为父进程。
一、储备知识:进程
- 进程可以看做程序的一次执行过程,在linux下每个进程有唯一的PID来标识进程。
特殊进程:
ID为0的是调度进程,该进程是内核的一部分,不执行任何磁盘上的程序
ID为1的是Init进程,init通常读取与系统有关的初始化文件(/etc/rc*文件、/etc/inittab文件、/etc/init.d/中的文件)
ID为2的是页守护进程,负责支持虚拟存储器系统的分页操作
- linux用进程表来储存正在运行的进程
命令ps aux可以查看所有正在运行的程序
ps -ef | grep 搜索内容可以查找想要的进程 - 进程在linux中呈树状结构,init为根节点,其它进程均有父进程,某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。
- fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
二、fork函数
#include <unistd.h>
pid_t fork(void);
//子进程返回0
//父进程返回子进程ID
//出错返回-1
fork函数被调用一次将返回两次,在子进程中返回0,在父进程中返回子进程的ID。
子进程获得父进程的数据空间、堆、栈副本
三、进程创建和死亡
init是永远不会死亡的。看下面的linux父子进程终止的先后顺序不同产生不同的结果:
1)父进程先于子进程终止:
此种情况就是孤儿进程。当父进程先退出时,系统会让init进程接管子进程 。这也是让程序进行后台运行的一种方式,系统apidaemon其实也是调用了这一过程
2)子进程先于父进程终止,而父进程又没有调用wait或waitpid函数
此种情况子进程进入僵尸状态,且会一直保持下去直到系统重启。子进程处于僵尸状态时,内核只保存进程的一些必要信息以备父进程所需。此时子进程始终占有着资源,同时也减少了系统可以创建的最大进程数。
僵尸进程:一个已经终止、但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放它仍占有的资源)的进程被称为僵尸进程(zombie)。ps命令将僵尸进程的状态打印为Z 。
3)子进程先于父进程终止,而父进程调用了wait或waitpid函数
此时父进程会等待子进程结束。