我正在阅读关于 Linux x86-64 系统的信号/ECF 的教科书章节(CS:APP,第 3 版,第 8 章,第 781 页),并遇到了这个问题:
sigsuspend 函数暂时用掩码替换当前的阻塞集,然后暂停进程,直到接收到一个信号,该信号的动作是运行处理程序或终止进程。如果该操作要终止,则该过程终止而不从 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. 我的直觉/理解哪里出了问题?