此答案上一版的主要部分是错误的。我为我的错误道歉。感谢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 Signal concepts 说:
每个线程都有一个“信号掩码”,它定义了当前阻止传递给它的一组信号。
应用到您的代码片段
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)。 oldmask 中的输出是添加 SIGRTMIN+1 之前的信号掩码。它可能已经包含也可能不包含 SIGRTMIN+1。进程的信号掩码已更改(如果您需要为线程设置信号掩码,则可以使用pthread_sigprocmask())从其当前值更改为包含 SIGRTMIN+1 的新值,并告知您旧值。
来自 cmets
如果我想阻止 SIGRTMIN+1,那么在我的第一个示例中使用 sigsuspend(&oldmask) 是错误的吗?
重大变化。
是的,这是错误的。调用sigsuspend(&oldmask) 会使您的线程进入睡眠状态,直到收到oldmask 中的信号之一。 oldmask 的内容是在您添加 SIGRTMIN+1 之前被阻止的信号集。
是的,这是错误的。调用sigsuspend(&oldmask) 会使您的线程进入睡眠状态,直到收到oldmask 中的信号not 之一。 oldmask 的内容是在您添加 SIGRTMIN+1 之前被阻止的一组信号。
以下两段被撤回,而不是必然被谴责为错误。我认为两者都有道理,尽管两者也有改进的余地。
您不使用sigsuspend() 来阻止信号本身;你用它来等待一组指定的信号之一到达。
如果你想忽略SIGRTMIN+1,那么你需要使用sigaction()或者你可以像你一样使用sigprocmask();专门阻止 SIGRTMIN+1 以及所有其他已被阻止的信号。
我是否正确理解它会像以前一样阻止相同的信号?
假设“它”是sigsuspend(),那么它将阻塞任何不在oldmask 中的信号,并等待oldmask 中的信号之一到达。
假设“它”是sigsuspend(),那么它将阻塞oldmask 中的任何信号并等待oldmask 中的not信号之一到达。
如果我这样做 sigsuspend(&mask) 那么它会阻止 SIGRTMIN+1 和 oldmask 中的所有信号,因为 sigprocmask(SIG_BLOCK, &mask, &oldmask)?
重大变化
绝对不!这将暂停线程,直到mask 中的信号之一到达。由于mask 中唯一的信号是 SIGRTMIN+1,只有当它到达时,sigsuspend() 才会返回。 sigprocmask() 报告了在oldmask 调用之前被阻止的内容;它根本没有修改mask(你的变量);它确实通过添加 SIGRTMIN+1 修改了进程的信号掩码。
绝对不是!这将暂停线程,直到mask 中的一个信号 not 到达。由于mask 中的唯一信号是 SIGRTMIN+1,因此只有该信号被阻塞,当任何其他信号到达时,它将被处理,sigsuspend() 将返回。 sigprocmask() 报告了在oldmask 调用之前被阻止的内容;它根本没有修改mask(你的变量);它确实通过添加 SIGRTMIN+1 修改了进程的信号掩码。
我强烈建议阅读或重新阅读 POSIX Signal concepts 和各种操纵信号处理的函数。 (是的,这在一定程度上是“医生,治愈你自己”的处方。)
如果这里还有错误,请告诉我。