[英]Explanation of sigsuspend needed
我需要澄清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"); }
这样,对于每个信号,我都会收到“收到的信号”吗?
上一版本答案的主要部分是错误的。 我为我的错误道歉。 我感谢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概念说:
每个线程都有一个“信号掩码”,用于定义当前阻止传递给它的信号集。
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以及已被阻止的所有其他信号。
我是否正确理解它会以同样的方式阻止相同的信号?
假设“它”是 sigsuspend()
则它将阻止任何信号没有在oldmask
并等待信号中的一个在oldmask
到达。
假设'它'是sigsuspend()
,那么它将阻止oldmask
任何信号并等待不在 oldmask
一个信号到达。
如果我做
sigsuspend(&mask)
,然后它会阻止SIGRTMIN + 1,所有的信号oldmask
因为sigprocmask(SIG_BLOCK, &mask, &oldmask)
重大变化
绝对不! 这将挂起线程,直到 mask
一个信号到达。由于 mask
唯一的信号是SIGRTMIN + 1,所以只有到达时才会返回sigsuspend()
。sigprocmask()
报告了在oldmask
调用之前被阻塞的oldmask
;它根本没有修改 mask
(你的变量);它确实通过添加SIGRTMIN + 1来修改进程的信号掩码。
绝对不! 这将暂停线程,直到其中一个信号不在 mask
。 由于mask
唯一的信号是SIGRTMIN + 1,只有该信号被阻塞,当任何其他信号到达时,它将被处理并且sigsuspend()
将返回。 sigprocmask()
报告了在oldmask
调用之前被阻塞的oldmask
; 它根本没有修改mask
(你的变量); 它确实通过添加SIGRTMIN + 1来修改进程的信号掩码。
我强烈建议阅读或重读POSIX Signal概念和操作信号处理的各种功能。 (是的,这部分是“医生,治愈你自己”的处方。)
如果这里仍有错误,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.