xwh*_*hyz 10 c unix signals process
我需要澄清sigsuspend主题.我有一个简化的例子
sigset_t mask, oldmask;
sigemptyset (&mask);
sigaddset (&mask, SIGRTMIN+1);
sigprocmask (SIG_BLOCK, &mask, &oldmask);
sigsuspend(&oldmask);
sigprocmask (SIG_UNBLOCK, &mask, NULL);
Run Code Online (Sandbox Code Playgroud)
以下是我对此的理解:
其次,让我们假设我在一个循环中有这样的sigsuspend并且到达了一些SIGRTMIN + 1信号.每个信号都会继续这样的循环吗?在某种队列?
while(1){
sigsuspend(&oldmask)
printf("recieved signal");
}
Run Code Online (Sandbox Code Playgroud)
这样,对于每个信号,我都会收到"收到的信号"吗?
Jon*_*ler 15
上一版本答案的主要部分是错误的.我为我的错误道歉.我感谢Wotim指出错误.
sigsuspend()
POSIX标准描述sigsuspend()
得相当清楚:
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
描述
该
sigsuspend()
函数必须用指向的信号集替换调用线程的当前信号掩码,sigmask
然后暂停该线程,直到传递一个信号,该信号的动作是执行信号捕获功能或终止进程.这不会导致进程上可能已挂起的任何其他信号在线程上挂起.如果行动是终止过程,则
sigsuspend()
永远不会返回.如果动作是执行信号捕获功能,sigsuspend()
则应在信号捕获功能返回后返回,信号掩码恢复到sigsuspend()
呼叫前存在的设置.无法阻止不可忽略的信号.这是由系统强制执行的,不会导致指示错误.
返回值
由于
sigsuspend()
无限期挂起线程执行,因此没有成功的完成返回值.如果发生返回,则返回-1并设置errno以指示错误.错误
该
sigsuspend()
IF函数将失败:
[EINTR]
调用进程捕获信号,并从信号捕获函数返回控制.
此外,POSIX Signal概念说:
每个线程都有一个"信号掩码",用于定义当前阻止传递给它的信号集.
该sigsuspend()
功能是旧pause()
功能的现代模拟.
主要变化:两个代码块反转.
它允许您将线程发送到睡眠状态,直到其中一个选定信号出现.如果你希望它在SIGRTMIN + 1到达之前休眠,你可以使用:
sigfillset(&mask);
sigdelset(&mask, SIGRTMIN+1);
sigsuspend(&mask);
Run Code Online (Sandbox Code Playgroud)
这会阻止除SIGRTMIN + 1之外的所有信号.
如果你想睡到SIGRTMIN + 1以外的信号到达,你可以使用:
sigemptyset(&mask);
sigaddset(&mask, SIGRTMIN+1);
sigsuspend(&mask);
Run Code Online (Sandbox Code Playgroud)
这仅阻止SIGRTMIN + 1.
Received signal
除非你在最后添加换行符,否则你的循环将无法可靠地打印(也许甚至不是;你可能需要fflush(stdout)
或等效).但是,如果在正常的事件过程中阻塞了&oldmask
SIGRTMIN + 1,然后设置为仅允许SIGRTMIN + 1,则在代码进入时可以可靠地传递信号sigsuspend()
.
您的描述sigprocmask()
不正确:
sigprocmask
将所有信号设置mask+oldmask
为阻止
当你这样做时:
sigset_t mask, oldmask;
sigemptyset(&mask);
sigaddset(&mask, SIGRTMIN+1);
sigprocmask(SIG_BLOCK, &mask, &oldmask);
Run Code Online (Sandbox Code Playgroud)
您将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概念和操作信号处理的各种功能.(是的,这部分是"医生,治愈你自己"的处方.)
如果这里仍有错误,请告诉我.