q09*_*987 6 c linux multiprocessing ubuntu-10.04
基于http://man7.org/tlpi/code/online/book/procexec/multi_SIGCHLD.c.html
int
main(int argc, char *argv[])
{
int j, sigCnt;
sigset_t blockMask, emptyMask;
struct sigaction sa;
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s child-sleep-time...\n", argv[0]);
setbuf(stdout, NULL); /* Disable buffering of stdout */
sigCnt = 0;
numLiveChildren = argc - 1;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = sigchldHandler;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
errExit("sigaction");
/* Block SIGCHLD to prevent its delivery if a child terminates
before the parent commences the sigsuspend() loop below */
sigemptyset(&blockMask);
sigaddset(&blockMask, SIGCHLD);
if (sigprocmask(SIG_SETMASK, &blockMask, NULL) == -1)
errExit("sigprocmask");
for (j = 1; j < argc; j++) {
switch (fork()) {
case -1:
errExit("fork");
case 0: /* Child - sleeps and then exits */
sleep(getInt(argv[j], GN_NONNEG, "child-sleep-time"));
printf("%s Child %d (PID=%ld) exiting\n", currTime("%T"),
j, (long) getpid());
_exit(EXIT_SUCCESS);
default: /* Parent - loops to create next child */
break;
}
}
/* Parent comes here: wait for SIGCHLD until all children are dead */
sigemptyset(&emptyMask);
while (numLiveChildren > 0) {
if (sigsuspend(&emptyMask) == -1 && errno != EINTR)
errExit("sigsuspend");
sigCnt++;
}
printf("%s All %d children have terminated; SIGCHLD was caught "
"%d times\n", currTime("%T"), argc - 1, sigCnt);
exit(EXIT_SUCCESS);
}
Run Code Online (Sandbox Code Playgroud)
这是我的理解:
sigprocmask(SIG_SETMASK,&blockMask,NULL)
调用进程的结果信号集应该是blockMask指向的集合.
题
为什么我们说下面的陈述?
如果子进程在父进程开始下面的sigsuspend()循环之前终止,则阻止SIGCHLD阻止其传递
换句话说,我不明白为什么sigprocmask用于根据sigprocmask语句的给定描述来阻止SIGCHLD.
好吧,我认为评论很清楚......
每当你调用fork()并想以任何方式与孩子互动时,都需要考虑竞争条件.如果孩子在父母之前跑了一段时间怎么办?或相反亦然?
在这种情况下,无法知道父母将在呼叫之后接听fork电话的时间sigsuspend.那么如果分叉的孩子完成它sleep并exit在父母调用之前调用sigsuspend呢?然后父母将收到一个SIGCHLD它忽略的......然后它会调用sigsuspend,它将永远不会返回因为SIGCHLD已经被传递.
唯一的100%解决方案是SIGCHLD 在调用之前fork阻塞,然后在入口处以原子方式解锁它sigsuspend.(处理这种竞争条件正是为什么sigsuspend需要信号掩码作为参数...如果你在呼叫之前尝试解锁信号sigsuspend,就会出现竞争状态;即信号可能在你开始等待之前被传递.改变信号mask然后输入wait必须是原子的,你必须阻止你想要等待的任何信号才能生成它.)