我正在阅读教科书上有关Linux x86-64系统的signal / ECF的一章(CS:APP,第三版,第8章,第781页),并且偶然发现了这一点:
sigsuspend函数用mask临时替换当前的阻塞集,然后挂起进程,直到收到一个信号,该信号的作用是运行处理程序或终止进程。如果该操作要终止,则该过程将终止而不从sigsuspend返回。如果该操作是要运行处理程序,则sigsuspend将在处理程序返回后返回,将被阻止的集恢复为调用sigsuspend时的状态。
sigsuspend函数等效于以下内容的原子(不间断)版本:
1 sigprocmask(SIG_BLOCK, &mask, &prev); 2 pause(); 3 sigprocmask(SIG_SETMASK, &prev, NULL);
据我所知,sigprocmask(SIG_BLOCK, &mask, &prev)
会导致被屏蔽的集与掩码进行或运算,即将掩码中的信号添加到已被屏蔽的集合中。但是代码正上方的文本(以及我查找的sigsuspend的手册页)上说sigsuspend“暂时替换当前的带掩码的阻止集”。对我来说,这听起来更像sigprocmask(SIG_SETMASK, &mask, &prev)
,在那儿,被阻止的设置被设置为等于掩码中的信号。
那么,为什么sigsuspend(&mask)
等同于上面的代码(第1-3行)而不是下面的代码(第4-6行)?在我对signal.h函数的直觉和/或理解上哪里出错了?
4 sigprocmask(SIG_SETMASK, &mask, &prev);
5 pause();
6 sigprocmask(SIG_SETMASK, &prev, NULL);
如果我不清楚,让我问一个具体问题(它可能会更好地解释我的直觉)。假设当前的阻止集对SIGCHLD进行编码,而sigset_t掩码对SIGINT进行编码。我叫sigsuspend(&mask)
。无论哪种代码解释正确(第1-3或4-6行),在调用sigsuspend之后立即传递的SIGINT信号都将被阻止/不会唤醒该过程。但是,如果在调用sigsuspend之后立即传递了SIGCHLD信号怎么办?该过程会唤醒/接收信号吗?我的直觉说,第1-3行将阻止SIGCHLD,而第4-6行则不会,因此显然1-3和4-6行并不等效。但是我的直觉还说,sigsuspend不应阻止SIGCHLD,因为它不在掩码中,因此第4-6行是正确的,如果在这种情况下第4-6行等效于sigsuspend,则sigsuspend不能等同于第1行3。我的直觉/理解哪里出错了?
答案 0 :(得分:2)
关于技术书籍(尤其是教科书)的事情是,您应始终了解是否有勘误表。
这本书的勘误的link显示:
第8章:出色的控制流程
...
...
p。 781.在第二段对sigsuspend
的描述中,第1行应为:
sigprocmask(SIG_SETMASK, &mask, &prev);
发表于10/28/2015。戴夫·奥哈拉隆