在进程运行时,由于某些原因会产生僵尸进程和孤儿进程,僵尸和孤儿两个词语形象的体现某进程的运行状态
僵尸进程:当进程加载到内存中时,需要向操作系统申请资源,正常情况下,当一个进程正常退出时,这个进程的资源会被他的父进程或者操作系统回收,如果这些资源在进程退出时没有被操作系统回收,就像一具已经僵硬的尸体,没人处理,形象的称这个进程为僵尸进程,如果僵尸进程一直不被回收,就造成了内存泄漏,试想一下,如果系统中的僵尸进程越来越多,操作系统自己的资源就越来越少,直到系统崩溃,下面模拟一下这种情况:
#include<stdio.h>
#include<unistd.h>
int main() {
pid_t pid = fork();
if(pid < 0) {
perror("fork");
return 1;
}
else if(pid == 0) {
//子进程
printf("我是子进程~~\n");
sleep(3);
printf("子进程退出~~\n");
}
else {
//父进程
printf("我是父进程~~\n");
sleep(5);
printf("父进程异常退出~~\n");
exit(1);
}
return 0;
}
运行结果:
在另一个窗口写一个监测a.out进程的shell脚本:while :;do ps aux | grep a.out | grep -v grep; sleep 1; echo "--------------------------------------------";done 在程序运行之后,监测到有这个进程如下图
在三秒后,子进程退出,这时父进程正在做自己的事情,子进程处于僵尸状态,正在等待父进程查看他的退出码,但在五秒之后父进程异常退出,异常退出的父进程应该没有能力去处理僵尸状态的子进程,但是发现在父进程结束之后,子进程也随即消失,为什么???,这个问题在孤儿进程之后回答
孤儿进程:假如一个父进程创建了一个子进程,父进程先退出,子进程就变成了孤儿进程,下面模拟一下孤儿进程:
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main() {
pid_t pid = fork();
if(pid < 0) {
perror("fork");
return 1;
}
else if(pid == 0) {
//子进程
printf("我是子进程~~\n");
pid_t ppid = getppid();
printf("c: my ppid :%d\n", ppid);
sleep(5);
ppid = getppid();
printf("c: my ppid :%d\n", ppid);
printf("子进程退出~~\n");
}
else {
//父进程
printf("我是父进程~~\n");
sleep(3);
printf("父进程退出~~\n");
}
return 0;
}
实验结果:
就算子进程变成了孤儿进程,但是当他退出时,资源依然需要被父进程回收,不然就变成了僵尸进程,其实情况也没有那么悲观,当一个子进程的父进程退出后,该子进程就会被操作系统的1号进程领养,当这个子进程退出时,他的资源就由操作系统回收
那么僵尸进程的资源如何回收?
1.子进程结束后,操作系统会发送SIGCHLD信号给父进程,父进程收到这个信号以后,执行waitpid()函数来回收子进程的资源
2.如果父进程异常退出,僵尸进程成为"孤儿进程",过继给1号进程init,1号进程就会回收这个子进程的资源