僵尸进程的分析

来源:互联网 发布:mac怎么设置虚拟打印机 编辑:程序博客网 时间:2024/06/16 04:55

当一个子进程结束后,他的父进程没有等待他(wait waitpid)清除他的所有资源时,它就变成一个僵尸进程。

在linux系统中,在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放. 但这样就导致了问题,如果进程不调用wait / waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。


那么可以通过杀掉他的父进程来把僵尸进程一起杀掉。

ps -aux  其中的ppid 就是一个僵尸进程的父进程 


僵尸进程产生
 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命令可以查看僵尸进程,一般具有标志:






[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. int main(){  
  4.     pid_t pid,pr;  
  5.     pid = fork();  
  6.     switch(pid){  
  7.   
  8.         case -1:  
  9.         printf("error");  
  10.         exit(EXIT_FAILURE);  
  11.   
  12.         case 0:  
  13.                 printf("child process\n");  
  14.         break;  
  15.   
  16.         default:  
  17.             printf("parent pid = %d\n",getpid());  
  18.             while(1)  
  19.                 sleep(2);  
  20.     }  
  21.     exit(0);  
  22. }  

 上面实例中,由于parent进程一直处于运行状态,child进程退出时候,parent并没有调用wait() 或者waitpid() 函数操作,就会产生僵尸进程。

运行该应用后,执行ps命令:


[plain] view plain copy
  1. qq@qq-Aspire-TC-606:~/qqzhong/tmp/c$ ps auxw|grep zombie  
  2. qq   4100  0.0  0.0   4196   356 pts/1    S+   16:41   0:00 ./zombie_tmp  
  3. qq   4101  0.0  0.0      0     0 pts/1    Z+   16:41   0:00 [zombie_tmp] <defunct>  



如何避免僵尸进程
fork  和 wait 成对出现
上面我们可以看到,产生僵尸进程的条件,为了避免产生僵尸进程,必须是吸纳fork 和 wait成对出现,wait在fork之后进行调用。
避免产生僵尸进程实例
根据上面的实例,我们增加处理操作,代码如下:


[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. int main(){  
  4.     pid_t pid,pr;  
  5.     pid = fork();  
  6.     switch(pid){  
  7.   
  8.         case -1:  
  9.         printf("error");  
  10.         exit(EXIT_FAILURE);  
  11.   
  12.         case 0:  
  13.                 printf("child process\n");  
  14.         break;  
  15.   
  16.         default:  
  17.             printf("parent pid = %d\n",getpid());  
  18.             while(pr = wait(NULL) !=-1)  
  19.                 ;  
  20.             while(1)  
  21.                 sleep(2);  
  22.     }  
  23.     exit(0);  
  24. }  

运行该应用,通过ps命令查看后如下

[plain] view plain copy
  1. qq@qq-Aspire-TC-606:~/qqzhong/tmp/c$ ps auxw|grep zombie  
  2. qq   4147  0.0  0.0   4196   356 pts/1    S+   16:45   0:00 ./zombie_tmp  
原创粉丝点击