代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#define CHILD_EXIT_SEC 4
void printsigset(sigset_t *set)
{
for (int i = 1; i < 32; i++)
{
if (sigismember(set, i) == 1)
putchar('1');
else
putchar('0');
}
puts("");
}
void do_sigchld(int sig)
{
int status;
pid_t pid;
while((pid = waitpid(0, &status, WNOHANG)) > 0) // 0:回收跟自己同组的子进程, WNOHANG:如果没有子进程存在,立即返回,即不阻塞
{
if (WIFEXITED(status))
printf("child %d exit %d\n", pid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("child %d cancel signal %d\n", pid, WTERMSIG(status));
}
}
int main(int argc, char *argv[])
{
pid_t pid;
int n = CHILD_EXIT_SEC;
sigset_t oldset;
//阻塞SIGCHLD
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, &oldset);
int i;
for (i = 0; i < 10; i++)
{
pid = fork();
if (pid == 0)
break;
else if (pid < 0)
{
perror("fork");
exit(1);
}
usleep(500*1000); //500毫秒
}
if (pid > 0)
{
//in parent
//先捕捉信号
struct sigaction act;
act.sa_handler = do_sigchld;
sigemptyset(&act.sa_mask);
act.sa_flags = 0; // sa_handler
sigaction(SIGCHLD, &act, NULL);
printf("parent: %d ----before-----\n", getpid());
printsigset(&oldset);
//再解除对SIGCHLD的阻塞
sigprocmask(SIG_UNBLOCK, &set, &oldset);
printf("parent: %d ----after-----\n", getpid());
printsigset(&oldset);
while(1)
{
printf("p pid = %d\n", getpid());
sleep(1);
}
}
else if (pid == 0)
{
//in child
printf("child: %d ----before-----\n", getpid());
printsigset(&oldset);
//解除对SIGCHLD的阻塞
sigprocmask(SIG_UNBLOCK, &set, &oldset);
printf("child: %d ----after-----\n", getpid());
printsigset(&oldset);
while(n--)
{
printf("c pid = %d\n", getpid());
sleep(1);
}
return i;
}
return 0;
}
运行结果