僵死进程

Linux僵死进程产生的原因以及如何避免产生僵死进程:

给进程设置僵死状态的目的是维护子进程的信息,以便父进程在以后某个时间获取。这些信息包括子进程的进程ID、终止状态以及资源利用信息(CPU时间,内存使用量等等)。如果一个进程终止,而该进程有子进程处于僵死状态,那么它的所有僵死子进程的父进程ID将被重置为1(init进程)。继承这些子进程的init进程将清理它们(init进程将wait它们,从而去除僵死状态)。

但通常情况下我们是不愿意留存僵死进程的,它们占用内核中的空间,最终可能导致我们耗尽进程资源。那么为什么会产生僵死进程呢?

僵死进程产生的原因:

我们知道在当前进程中生成一个子进程,一般需要调用fork这个系统调用,foek这个函数的特点就是一次调用,两次返回,一次返回到父进程中,一次返回到子进程中,我们可以通过它的返回值来判断返回点。如果子进程先于父进程退出,同时父进程没有调用wait/waitpid,则该子进程将成为僵死进程。通过ps命令,我们可以看到该进程的状态为z(表示僵死)。

如何避免产生僵死进程?

我们知道了僵死进程产生的原因,因此,一般为了防止产生僵死进程,在fork子进程之后我们都要wait它们;同时,当子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵死进程的目的。

代码如下:

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

void sig_chld(int signo)
{
    pid_t pid;
    int stat;
    pid = wait(&stat);
   printf("child%dexit\n",pid);
    return;
}

int main()
{
    signal(SIGCHLD,&sig_chld);
}

代码分析:

先在main中给SIGCHLD信号注册一个信号处理函数(sig_chld),然后在子进程退出的时候,内核递交一个SIGCHLD的时候,就会被主进程捕获而进入信号处理函数sig_chld,然后再在sig_chld中调用wait,就可以清理退出的子进程。这样退出的子进程就不会成为僵死进程。

然后,即使我们捕获SIGCHLD信号并且调用wait来清理退出的进程,仍然不能彻底避免产生的僵死进程;即当建立信号处理函数并在其中调用wait并不足以防止出现僵死进程,其原因再欲:所有5个i你好都在处理函数执行之前产生,而信号处理函数只产生一次,因为unix信号一般是不排队的。更为严重的是,本问题是不确定的,依赖于客户FIN到达服务器主机的时机,信号处理函数执行的次数并不稳定。

正确的解决办法就是调用waitpid,这个办法的方法为:信号处理函数中,在一个循环中调用waitpid以获取所有已终止子程序的状态。我们必须指定WNOHANG熏香,他告知waitpid在用尚未终止的子进程在运行时不要阻塞(我们不能再循环内调用wait,因为没有办法防止wait再尚有未终止的子进程再运行时阻塞,wait将会阻塞到现有的子进程中第一个终止为止)。

如果父进程不关心子进程什么时候结束,呢么可以用signal(SIGCHLD,SIG_IGN)通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收,并不再给父进程发送信号/或者用sugaction函数为SIGCHLD设置SA_NOCLDWAIY,这样子进程结束后,就不会进入僵死状态struct sigaction sa。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值