一、 僵尸进程
-
什么是僵尸进程
僵尸状态是一个比较特殊的状态,当进程退出并且父进程没有读取到子进程退出的返回码时就会产生僵尸进程。僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出码状态。所有,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入僵尸状态。 -
代码实现一下:
#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
int main()
{
pid_t id = fork();
if(id < 0)
{
perror("fork");
return 1;
}
else if(id > 0)
{
// parent
printf("parent[%d] is sleeping...\n", getpid());
sleep(30);
}
else
{
printf("child[%d] is begin Z...\n", getpid());
sleep(5);
exit(EXIT_SUCCESS);
} return 0;
}
结果如下:
3. 僵尸进程的危害及解决方法
危害:
如果有大量的僵尸进程驻在系统之中,必然消耗大量的系统资源。但是系统资源是有限的,因此当僵尸进程达到一定数目时,系统因缺乏资源而导致奔溃。
解决方法:
1)杀死僵尸进程的父进程
将其父进程杀死,那么它的子进程,即僵尸进程会变成孤儿进程,由系统来回收。但是这种做法在大多数情况下都是不可取的,如父进程是一个服务器程序,如果为了回收其子进程的资源,而杀死服务器程序,那么将导致整个服务器崩溃,得不偿失。显然这种回收进程的方式是不可取的,但其也有一定的存在意义。
2)SIGCHLD 信号处理
我们都知道wait函数是用来处理僵尸进程的,但是进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止
二、孤儿进程
-
什么是孤儿进程
一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。子进程死亡需要父进程来处理,那么意味着正常的进程应该是子进程先于父进程死亡。当父进程先于子进程死亡时,子进程死亡时没父进程处理,这个死亡的子进程就是孤儿进程。但孤儿进程与僵尸进程不同的是,由于父进程已经死亡,系统会帮助父进程回收处理孤儿进程。所以孤儿进程实际上是不占用资源的,因为它终究是被系统回收了。不会像僵尸进程那样占用ID,损害运行系统。2.代码实现一下
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t ret=fork();
if(ret<0)
{
perror("fork");
return 1;
}
else if(ret==0)
{
printf("child,pid:%d\n",getpid());
sleep(10);
}
else
{
printf("father,pid:%d\n",getpid());
sleep(3);
exit(0);
}
return 0;
}
结果如下:
重启另一个终端: