#include
#include
#include
#include
#include
#include
#include
//父进程循环创建三个子进程, 并用sigchld完成对子进程的回收
/*
1. fork 循环3次 if()
2. 在父进程中注册信号处理函数,在子进程中睡眠,然后不同时间段退出
3. 设置未决信号集 , 阻塞信号集 , 将sigchld添加到阻塞信号集合中, 在完成信号注册后,解除对sigchld信号的阻塞. 这一步的目的是 : 为了防止父进程还没有完成对sigchld信号的注册, 子进程就结束了, 没有利用到sigchld回收子进程, 子进程就变成了僵尸进程
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask , SIGCHLD);
sigprocmask(SIG_BLOCK , &mask , NULL);
//注册
sigprocmask(SIG_UNBLOCK , &mask , NULL);
4. 注册信号处理函数的过程: 利用sigaction(SIGCHLD , )
struct sigaction act;
act.sa_handler = chld;
sigemptyset(&act.sa_mask); //清空信号集中的信号
act.sa_flags = 0;
sigaction(SIGINT , &act , NULL);
*/
void chld(int signo)
{
pid_t wpid;
while(1)
{
wpid = waitpid(-1 , NULL , WNOHANG);
if(wpid == 0 && wpid < 0) //子进程还活着 没子进程活着了
{
break;
}else if(wpid>0) //子进程退出 返回子进程pid
{
printf("exit . child sig = [%d]\n" , wpid);
}
}
}
int main()
{
int i;
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask ,SIGCHLD);
sigprocmask(SIG_BLOCK , &mask , NULL);
for(i=0; i<3; i++)
{
int pid = fork();
if(pid < 0)
{
perror("fork error");
}
else if(pid > 0)
{
printf("father pid=[%d]\n", getpid());
}
else
{
printf("son pid = [%d]\n",getpid());
break; //1. err1 这里应该break ,防止子进程创建子进程
}
}
if(i==0)
{
printf("i==[%d], son pid = [%d]\n",i, getpid());
sleep(1);
}
if(i==1)
{
printf("i==[%d], son pid = [%d]\n",i, getpid());
sleep(2);
}
if(i==2)
{
printf("i==[%d], son pid = [%d]\n",i, getpid());
sleep(1);
}
else if(i==3)
{
struct sigaction act;
act.sa_handler = chld;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
//这里加延时 是为了模拟: 父进程还没来得及注册信号处理函数 , 子进程就全部退出了的情形!
sigaction(SIGCHLD , &act , NULL);
sigprocmask(SIG_UNBLOCK , &mask ,NULL);
while(1)
{
sleep(1); //sleep(1) 是为了防止空转速度过快
}
}
return 0;
}
holo@holo:~/fwq$ ./sigchld
father pid=[33860]
son pid = [33861]
i==[0], son pid = [33861]
father pid=[33860]
son pid = [33862]
i==[1], son pid = [33862]
father pid=[33860]
son pid = [33863]
i==[2], son pid = [33863]
exit . child sig = [33861]
exit . child sig = [33863]
exit . child sig = [33862]^C