消除僵尸进程涉及到以下两个小问题。
1、如何使用SIGCHLD信号解决僵尸进程?
利用sigaction函数捕捉SIGCHLD信号,执行包含waitpid函数的回调函数。
2、子进程很快就结束,父进程还没有注册完信号捕捉,就会有多个子进程结束,发出多个信号,由于未决信号集只能记录一个信号,其余的被忽视。导致不能杀死所有的僵尸进程。
下面是具体的编程。
/*
SIGCHLD信号产生的条件
1、子进程结束
2、子进程暂停
3、子进程继续运行
都会给父进程发送该信号,父进程默认忽略该信号
使用SIGCHLFD解决僵尸进程问题。
*/
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<signal.h>
#include<sys/wait.h>
void myFun(int num){
printf("捕捉到信号%d\n",num);
// 回收子进程资源
while(1){
int ret = waitpid(-1,NULL,WNOHANG);
if(ret > 0){
printf("child die, pid = %d\n",ret);
}
else if(ret == 0){
// 说明还有子进程或者;
break;
}
else if(ret == -1){
//说明没有子进程
break;
}
}
}
int main()
{
// 设置阻塞信号集,阻塞SIGCHLD
sigset_t set;
sigemptyset(&set);
sigaddset(&set,SIGCHLD);
sigprocmask(SIG_BLOCK,&set,NULL);
pid_t pid;
for(int i = 0; i < 20;i++){
pid = fork();
if(pid == 0)
break;
}
if(pid > 0){
// 父进程
// 捕捉子进程死亡时的SIGCHLD信号
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = myFun;
sigemptyset(&act.sa_mask);
sigaction(SIGCHLD,&act,NULL);
// 注册完信号捕捉以后,解除阻塞
sigprocmask(SIG_UNBLOCK,&set,NULL);
while(1){
printf("parent process pid : %d\n", getpid());
sleep(2);
}
}
else if(pid == 0){
//子进程
printf("child process pid = %d\n",getpid());
}
return 0;
}
提前设置好阻塞信号集,阻塞SIGCHLD。