这个答案的前一版的主要部分是错误的。我为我的错误道歉。我感谢Wotim指出错误。
POSIX 的定义sigsuspend()
POSIX 标准sigsuspend()
相当清楚地描述:
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
描述
该sigsuspend()
函数应将调用线程的当前信号掩码替换为所指向的信号集,sigmask
然后暂停线程,直到传递一个信号,该信号的作用是执行信号捕获函数或终止进程。这不会导致任何其他可能在进程上挂起的信号在线程上变为挂起。
如果该操作是终止进程,则sigsuspend()
永远不会返回。如果该动作是执行信号捕获函数,sigsuspend()
则应在信号捕获函数返回后返回,信号掩码恢复为sigsuspend()
调用前存在的集合。
无法阻止无法忽略的信号。这是由系统强制执行的,不会导致指示错误。
返回值
由于sigsuspend()
无限期暂停线程执行,所以没有成功完成返回值。如果发生返回,则应返回 -1 并设置 errno 以指示错误。
错误
如果出现以下情况,该sigsuspend()
功能将失败:
[EINTR]
调用进程捕获信号,并从信号捕获函数返回控制。
此外,POSIX信号概念说:
每个线程都有一个“信号掩码”,它定义了当前阻止传递给它的信号集。
应用到您的代码片段
该sigsuspend()
函数是旧pause()
函数的现代类似物。
主要变化:两个代码块颠倒了。
它允许您将线程发送到睡眠状态,直到其选定的信号之一发生。如果您希望它在 SIGRTMIN+1 到达之前一直休眠,请使用:
sigfillset(&mask);
sigdelset(&mask, SIGRTMIN+1);
sigsuspend(&mask);
这会阻塞除 SIGRTMIN+1 之外的所有信号。
如果你想睡觉直到 SIGRTMIN+1 以外的信号到达,你使用:
sigemptyset(&mask);
sigaddset(&mask, SIGRTMIN+1);
sigsuspend(&mask);
这仅阻止 SIGRTMIN+1。
除非您在末尾添加换行符,否则您的循环将无法Received signal
可靠打印(甚至可能不会;您可能需要fflush(stdout)
或等效)。但是,如果您在正常的事件过程中阻止了 SIGRTMIN+1,然后设置&oldmask
为仅允许 SIGRTMIN+1,那么当您的代码位于sigsuspend()
.
您的描述sigprocmask()
不正确:
sigprocmask
将所有信号设置mask+oldmask
为阻塞
当你这样做时:
sigset_t mask, oldmask;
sigemptyset(&mask);
sigaddset(&mask, SIGRTMIN+1);
sigprocmask(SIG_BLOCK, &mask, &oldmask);
您将 SIGRTMIN+1 添加到阻塞信号列表中(因为您使用了 SIG_BLOCK 并且mask
仅包含 SIGRTMIN+1)。in 的输出oldmask
是添加 SIGRTMIN+1 之前的信号掩码。它可能已经包含也可能不包含 SIGRTMIN+1。pthread_sigprocmask()
进程的信号掩码从其当前值更改为包含 SIGRTMIN+1 的新值(如果您需要为线程设置信号掩码,则改为使用),您会被告知旧值。
从评论中
sigsuspend(&oldmask)
如果我想阻止 SIGRTMIN+1,那么在我的第一个示例中使用是错误的吗?
重大变化。
是的,这是错误的。调用sigsuspend(&oldmask)
会使您的线程进入睡眠状态,直到oldmask
收到其中一个信号。的内容oldmask
是在您添加 SIGRTMIN+1 之前被阻止的信号集。
是的,这是错误的。调用sigsuspend(&oldmask)
将您的线程发送到睡眠状态,直到收到未输入的信号之一oldmask
。的内容oldmask
是在您添加 SIGRTMIN+1 之前被阻止的信号集。
以下两段被撤回,而不是必然被谴责为错误。我认为两者都有真实的元素,尽管两者也有改进的余地。
您不使用sigsuspend()
阻止信号本身;你用它来等待一组指定的信号之一到达。
如果要忽略SIGRTMIN+1,则需要使用sigaction()
,也可以照常使用sigprocmask()
;专门阻止 SIGRTMIN+1 以及所有其他已被阻止的信号。
我是否正确理解它会像以前一样阻止相同的信号?
假设“它”是sigsuspend()
,那么它将阻止任何未输入oldmask
的信号并等待其中一个信号oldmask
到达。
假设“它”是sigsuspend()
,那么它将阻止任何信号进入oldmask
并等待其中一个未进入的信号oldmask
到达。
如果我这样做sigsuspend(&mask)
了,它会阻止 SIGRTMIN+1 和所有信号,oldmask
因为sigprocmask(SIG_BLOCK, &mask, &oldmask)
?
重大变化
绝对不!这将暂停线程,直到其中一个信号mask
到达。由于唯一的信号mask
是 SIGRTMIN+1,只有当它到达时才会sigsuspend()
返回。sigprocmask()
报告在调用之前被阻止的内容oldmask
;它根本没有修改mask
(你的变量);它确实通过添加 SIGRTMIN+1 修改了进程的信号掩码。
绝对不!这将挂起线程,直到未输入的信号之一mask
到达。由于唯一的信号mask
是 SIGRTMIN+1,因此只有该信号被阻塞,当任何其他信号到达时,它将被处理并sigsuspend()
返回。sigprocmask()
报告在调用之前被阻止的内容oldmask
;它根本没有修改mask
(你的变量);它确实通过添加 SIGRTMIN+1 修改了进程的信号掩码。
我强烈建议阅读或重读 POSIX Signal 概念和操纵信号处理的各种函数。(是的,这部分是“医生,治愈你自己”的处方。)
如果这里还有错误,请告诉我。