Sigsuspend等同于sigprocmask,pause,sigprocmask的原子序列?

时间:2019-04-18 05:48:34

标签: c exception signals signal-handling multiple-processes

我正在阅读教科书上有关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。我的直觉/理解哪里出错了?

1 个答案:

答案 0 :(得分:2)

关于技术书籍(尤其是教科书)的事情是,您应始终了解是否有勘误表

这本书的勘误的link显示:

  

第8章:出色的控制流程
  ...
  ...
  p。 781.在第二段对sigsuspend的描述中,第1行应为:
  sigprocmask(SIG_SETMASK, &mask, &prev);
  发表于10/28/2015。戴夫·奥哈拉隆