我需要澄清sigsuspend主题。 我有一个简化的例子
sigset_t mask, oldmask;
sigemptyset (&mask);
sigaddset (&mask, SIGRTMIN+1);
sigprocmask (SIG_BLOCK, &mask, &oldmask);
sigsuspend(&oldmask);
sigprocmask (SIG_UNBLOCK, &mask, NULL);
以下是我对此的理解:
其次,让我们假设我在一个循环中有这样的sigsuspend并且到达了一些SIGRTMIN + 1信号。每个信号都会继续这样的循环吗?在某种队列中?
while(1){
sigsuspend(&oldmask)
printf("recieved signal");
}
所以对于每个信号我都打印了“收到的信号”?
答案 0 :(得分:14)
上一版本答案的主要部分是错误的。我为我的错误道歉。我感谢Wotim指出错误。
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说:
每个线程都有一个&#34;信号掩码&#34;它定义了当前阻止传递给它的信号集。
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的新值,并且你会被告知旧的价值。
如果我想阻止SIGRTMIN + 1,那么在我的第一个例子中使用
sigsuspend(&oldmask)
是错误的吗?
重大变化。
是的,这是错的。调用 sigsuspend(&oldmask)
会让您的线程进入睡眠状态,直到收到oldmask
中的一个信号。 oldmask
的内容是在添加SIGRTMIN + 1之前被阻止的信号集。
是的,这是错的。调用sigsuspend(&oldmask)
会使您的线程进入睡眠状态,直到收到oldmask
中的其中一个 信号为止。 oldmask
的内容是在添加SIGRTMIN + 1之前被阻止的信号集。
以下两段被撤回而不一定被视为错误。我认为两者都有真实的要素,尽管两者都有改进的余地。
您不使用 sigsuspend()
来阻止信号本身;你用它来等待一组指定的信号到达。
如果你想忽略SIGRTMIN + 1,那么你需要使用 sigaction()
,或者像你一样使用sigprocmask()
;它专门阻止SIGRTMIN + 1以及已被阻止的所有其他信号。
我是否正确理解它会以同样的方式阻止相同的信号?
假设&#39;它&#39;是 sigsuspend()
,然后它会阻止oldmask
以外的任何信号并等待oldmask
中的一个信号到达。
假设&#39;它&#39;是sigsuspend()
,然后它会阻止oldmask
中的任何信号并等待oldmask
中 之一的信号到达。
如果我
sigsuspend(&mask)
,那么由于oldmask
,它会阻止SIGRTMIN + 1和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 concepts以及操纵信号处理的各种函数。 (是的,这部分是处方&#34;医生,治愈你自己&#34;。)
如果此处仍有错误,请告诉我。