Linux——僵死进程和孤儿进程

一:定义

         首先明白,在linux系统中,子进程是通过父进程创建的,子进程自身再创建新的进程。并且父进程和子进程是异步运行的,即父进程永远无法预测子进程何时结束,当然也就不知道何时去收集子进程的退出信息了。

孤儿进程:在一个父进程退出后,剩余的它的一个子进程或者多个子进程仍然在运行,并没有退出,那么这些子进程就                   会变成孤儿进程,这些孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

僵死进程:一个进程使用了fork语句创建子进程,当子进程退出后,而父进程并没有能获取到子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。可以使用ps -e命令查看进程,可以查看到僵死的子进程(进程后有<defunct>字样)

二:为什么僵死进程不利于我们的进程处理呢?

       进程新生成时,必须先分配PCB结构,后才生成进程主体。一般在进程结束时先释放主体,然后才会释放PCB(进程控制块,一个PCB大概1.7K),但是在僵死进程中,当进程的主体释放,但是PCB结构依旧不释放。那么实际上你这个子进程中的有效数据只有4个字节,不释放PCB 的同时,将在这个子进程中就使得剩下的内存空间既无法释放也无法得到重新利用,所以会造成大量的内存浪费。

举例生成一个僵死进程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> 

int main ()
{
        pid_t p = fork();//进行fork操作,创建子进程
	if (p == -1)	
          {		
              printf("ERROR\n");	
          }	
        else if (p == 0)	
          {		
               printf("Child pid is:%d\n",getpid());   //子进程           
          }
	else 	
           {		
              while (1)		
                {			
                   printf("Father pid is:%d\n",getpid());    //父进程		
                   sleep(1);		//睡眠一秒
                }	
           }
     exit(0);
}

编译运行之后,会打印输出一次子进程的pid,随后一直是父进程打印自己的pid。  

三:如何处理僵死进程呢

方法一:wait/waitpid函数: Pid_t wait(int *reval)

        既然是父进程没有收到子进程的退出信息,那么我们给它用一个来使得能收到就OK了。wait函数就是用来应对这种情况的,父进程在调用wait函数之后就可以将自己阻塞,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。其中的参数reval用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,我们就可以设定这个参数为NULL

例如:pid = wait(NULL

在原代码中的父进程块中也只需要添加 wait(NULL),再运行的时候就会发现僵死进程已经被处理掉。

 

但是这样会出现一个问题:

在阻塞的过程中,父进程停止了自己的运行。在实际应用中我们不可能为了处理一个僵死进程而令父进程一直wait。并且一个wait函数只能处理一个僵死进程,作用十分有限。

那么就是能不能子进程在退出的时候它自己发出一个信号,来告诉父进程:我要退出了,你快点来处理我吧!

答案当然是可以的!

方法二:使用信号

信号是系统预先定义好的特定的事件,信号可以被产生,也可以被接收,产生和接收的实体就是进程)

  只需要在父进程块中加入一行代码:signal(SIGCHLD,SIG_IGN);

   将 SIGCHLD信号的操作设为SIG_IGN     
   signal(SIGCHLD,SIG_IGN);

   就可以不产生僵死进程了。调用这个signal函数就定义了父进程对子进程结束后返回的SIGCHLD信号的响应方式:忽略信号的响应方式有:默认   忽略   自定义),这种方式可以保持异步,即处理僵死进程的同时,父进程还可以继续运行不受影响。


 

 

 

猜你喜欢

转载自blog.csdn.net/qq_41321905/article/details/83902911