0 僵尸进程
僵尸进程是指某进程已经退出,然后其父进程还没有调用wait(),waitpid()等对其进程退出处理(收尸),所以这种进程成为僵尸进程。
1 孤儿进程
孤儿进程是其父进程在其之前退出,自己由init进程收养的进程。由于内核定义每一个进程必须要有父进程,所以内核对孤儿进程的处理是将其父进程设置为init进程。
2 fork()产生孤儿进程和僵尸进程
话不多少,上code:
#include <stdio.h>
#include <unistd.h>
void main(){
pid_t pson1, pson2, pson3;
int pp = 1;
printf("\n");
if((pson1 = fork())<0){
printf("fork error. \n");
exit(0);
} else if (pson1 == 0){ //son1
sleep(1);
printf("son1 pid: %d, my father pid %d\n", getpid(), getppid());
if((pson2 = fork()) < 0){
printf("fork error. \n");
exit(0);
} else if (pson2 == 0){ //son2
sleep(1);
printf("son2 pid: %d, my father pid %d\n", getpid(), getppid());
sleep(2); //wait son1 to exit();
printf("son2 pid: %d, my father pid %d\n", getpid(), getppid());
exit(0);
}
else { //son1
sleep(2);
printf("son1 exit();\n");
exit(0); //son1 exit();
}
}
else{ //parent
printf("father pid: %d, my father pid %d\n", getpid(), getppid());
sleep(5);
printf("father pid: %d, my father pid %d\n", getpid(), getppid());
}
exit(0);
}
root:~/apue/mycode# ./fork
father pid: 5408, my father pid 5117
son1 pid: 5409, my father pid 5408
son2 pid: 5410, my father pid 5409
son1 exit();
son2 pid: 5410, my father pid 1
father pid: 5408, my father pid 5117
root:~/apue/mycode# echo $$
5117
root:~/apue/mycode#
在结果中我们可以看出,当前shell 的进程是 5117.
程序的主进程(下称为父进程)是5408.主进程fork()出子进程1(pson1)是5409.
子进程1 fork()出子进程2(pson2)是5410.
然后子进程1退出,子进程1变为僵尸进程;同时子进程2丢失父进程,变为孤儿进程。
下为按时间分析程序执行情况:
第0秒 在最开始,父进程进行第一次fork(),产生 pson1 进程。
pson1 = fork()
此时父进程打印一行信息,而pson1进程阻塞一秒,parent进程阻塞5s。
father pid: 5408, my father pid 5117
第1秒 pson1 阻塞结束,打印一行信息;然后pson1开始fork(),生成pson2,同时pson1 阻塞2s、pson2 阻塞1s。
son1 pid: 5409, my father pid 5408
第2秒 pson2 阻塞结束,打印自己的pid和ppid,然后pson2 阻塞2s。
son2 pid: 5410, my father pid 5409
第3秒 pson1 阻塞结束,打印退出信息,并退出进程。此时partent进程在阻塞中,未对其进程回收,所以pson1为僵尸进程。
son1 exit();
第4秒 pson2 阻塞结束,打印自己的pid和ppid。可见其ppid已经是1了,所以此时pson2为孤儿进程。
son2 pid: 5410, my father pid 1
第5秒 father进程阻塞结束,打印自己的pid和ppid。
father pid: 5408, my father pid 5117
第5秒后 father进程退出,pson1和pson2也被回收,僵尸进程和孤儿进程都被消失。
3 相关知识
1 命令 ~ ps -ef |grep $(execname$ |grep -v grep 可以观察对应的进程情况。
2 命令 ~ echo $$ 可以看当前bash的pid。