Linux---僵尸进程的解决办法

僵尸进程

子进程退出后,资源没有释放,处于僵死状态。

产生原因: 子进程优先于父进程退出,父进程正在执行其他操作,没有关注子进程退出,这时候操作系统为了保护子进程退出的原因,不会释放子进程中的资源,子进程既没有运行,也没有退出,处于僵死状态,成为僵尸进程。

通常情况下解决僵尸进程的办法就是:
waitpid(pid_t pid,int * status,int options);
pid:子进程的操作句柄

  • pid<-1 等待进程组识别码为 pid 绝对值的任何子进程。
  • pid=-1 等待任何子进程,相当于 wait()。
  • pid=0 等待进程组识别码与目前进程相同的任何子进程。
  • pid>0 等待任何子进程识别码为 pid 的子进程。

status:保存子进程退出原因。

  • 如果不需要进程退出原因,则设置为NULL

options:存储waitpid函数的等待方式。

  • 为0默认阻塞等待。
  • WNOHANG 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若结束,则返回该子进程的ID。
  • WUNTRACED 若子进程进入暂停状态,则马上返回,但子进程的结束状态不予以理会。WIFSTOPPED(status)宏确定返回值是否对应与一个暂停子进程。
    子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况:
  • WIFEXITED(status)如果若为正常结束子进程返回的状态,则为真;对于这种情况可执行WEXITSTATUS(status),取子进程传给exit或_eixt的低8位。
  • WEXITSTATUS(status)取得子进程 exit()返回的结束代码,一般会先用
    WIFEXITED 来判断是否正常结束才能使用此宏。
  • WIFSIGNALED(status)若为异常结束子进程返回的状态,则为真;对于这种情况可执行WTERMSIG(status),取使子进程结束的信号编号。

返回值:成功返回子进程的pid,失败返回0。

//使用waitpid等待子进程退出
int main()
{ 
        signal(SIGCHLD,sigcb);
        pid_t pid = fork();
        if(pid == 0)
        {
                sleep(5);//子进程睡眠5秒钟后退出
                exit(0);
        }
        wait(-1,NULL,0);
        while(1)
        {
                printf("this is parents\n");
        }
        return 0;
}

如果waitpid为阻塞等待,则父进程一直在等子进程退出,直到子进程退出后才执行自己的操作,有没有一种父进程在执行自己的操作,当子进程退出信号发出时,父进程再来释放子进程。

如果这样我们需要先知道子进程退出时,操作系统给父进程发送什么样的信号,来通知父进程。
17号信号:SIGCHLD
在这里插入图片描述
但是这个SIGCHLD为进程默认忽略处理信号,这下我们知道为什么父进程不会注意子进程退出。
现在我们知道子进程退出时,操作系统会给父进程发送17号信号,但是我们如何自定义处理该信号呢?
signal自定义信号处理函数。

//我们通过信号处理函数来通知父进程
void sigcb(int signo)
{
        wait(-1,NULL,0);
}

int main()
{ 
        signal(SIGCHLD,sigcb);
        pid_t pid = fork();
        if(pid == 0)
        {
                sleep(5);//子进程睡眠5秒钟后退出
                exit(0);
        }
        while(1)
        {
                printf("this is parents\n");
        }
   }

但是这样做会产生一个问题:如果父进程有多个子进程呢,由于SIGCHLD信号为非可靠信号,在信号的集合中只保存一份,所以在调用signal函数时,会出现想要释放多个子进程,但事实上只释放一个,导致子进程没有完全处理,同样会产生僵尸进程。

解决办法:循环调用waitpid函数,防止出现进程没有完全处理的情况。

void sigcb(int signo)
{
        while(wait(-1,NULL,0)>0);//如果有子进程退出,则循环处理       	
}

int main()
{ 
        signal(SIGCHLD,sigcb);
        pid_t pid = fork();
        if(pid == 0)
        {
                sleep(5);//子进程睡眠5秒钟后退出
                exit(0);
        }
        while(1)
        {
                printf("this is parents\n");
        }
   }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值