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)或等效).但是,如果在正常的事件过程中阻塞了&oldmaskSIGRTMIN + 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概念和操作信号处理的各种功能.(是的,这部分是"医生,治愈你自己"的处方.)
如果这里仍有错误,请告诉我.