僵尸进程产生
Linux进程退出并不代表被删除
在Linux环境下,当某个进程退出时并不代表该进程在系统中已经被删除,还有一些包含进程状态等数据保存在系统中,若不人为进行删除,则会一直囤积在系统中,久而久之就会产生大量剩余数据。
僵尸进程基本概念
Linux系统中,出了Init进程,其他所有进程都是通过parent进行fork出来的,我们成为child进程,当child进程退出后,内核中包含child进程的数据没有被删除,这种情况就是僵尸进程。一般情况下,每个进程在退出之后,都会发送一个SIGCHLD信号给它的parent进程,默认情况下,parent进程是不处理该信号事件。
僵尸进程产生的条件
当child进程退出时候,系统会发送一个SIGCHLD信号给它对应的parent进程,parent进行若不处理该信号,则会产生僵尸进程现象,若通过调用wait() 或者waitpid()函数则会处理该事件,就不会产生僵尸进程。
对于child进程和parent进程来说,有两种情景,就是谁先退出,若parent进程先退出,则child进程会被托付给Init进程,Init进程则有对SIGCHLD信号的处理,不会产生僵尸进程;若child进程先退出,parent进程一直没有退出,也没有执行对SIGCHLD信号处理操作,则会产生僵尸进程。
僵尸进程产生实例
我们利用ps命令可以查看僵尸进程,一般具有标志:
#include <stdio.h>
#include <stdlib.h>
int main(){
pid_t pid,pr;
pid = fork();
switch(pid){
case -1:
printf("error");
exit(EXIT_FAILURE);
case 0:
printf("child process\n");
break;
default:
printf("parent pid = %d\n",getpid());
while(1)
sleep(2);
}
exit(0);
}
上面实例中,由于parent进程一直处于运行状态,child进程退出时候,parent并没有调用wait() 或者waitpid() 函数操作,就会产生僵尸进程。
运行该应用后,执行ps命令:
qq@qq-Aspire-TC-606:~/qqzhong/tmp/c$ ps auxw|grep zombie
qq 4100 0.0 0.0 4196 356 pts/1 S+ 16:41 0:00 ./zombie_tmp
qq 4101 0.0 0.0 0 0 pts/1 Z+ 16:41 0:00 [zombie_tmp] <defunct>
如何避免僵尸进程
fork 和 wait 成对出现
上面我们可以看到,产生僵尸进程的条件,为了避免产生僵尸进程,必须是吸纳fork 和 wait成对出现,wait在fork之后进行调用。
避免产生僵尸进程实例
根据上面的实例,我们增加处理操作,代码如下:
#include <stdio.h>
#include <stdlib.h>
int main(){
pid_t pid,pr;
pid = fork();
switch(pid){
case -1:
printf("error");
exit(EXIT_FAILURE);
case 0:
printf("child process\n");
break;
default:
printf("parent pid = %d\n",getpid());
while(pr = wait(NULL) !=-1)
;
while(1)
sleep(2);
}
exit(0);
}
运行该应用,通过ps命令查看后如下
qq@qq-Aspire-TC-606:~/qqzhong/tmp/c$ ps auxw|grep zombie
qq 4147 0.0 0.0 4196 356 pts/1 S+ 16:45 0:00 ./zombie_tmp