繁体   English   中英

需要解释sigsuspend

[英]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);

以下是我对此的理解:

  • sigemptyset清除信号列表(掩码) - 因为它是用当前阻塞的信号初始化的(?)
  • sigaddset将SIGRTMIN + 1添加到掩码中
  • sigprocmask设置要阻止掩码+旧掩码中的所有信号
  • sigsuspend(&oldmask)挂起线程执行,直到其中一个被阻塞的信号到达? 如果我想阻止SIGRTMIN + 1,是不是应该有sigsuspend(&mask)?

    其次,让我们假设我在一个循环中有这样的sigsuspend并且到达了一些SIGRTMIN + 1信号。 每个信号都会继续这样的循环吗? 在某种队列?

     while(1){ sigsuspend(&oldmask) printf("recieved signal"); } 

    这样,对于每个信号,我都会收到“收到的信号”吗?

  • 上一版本答案的主要部分是错误的。 我为我的错误道歉。 我感谢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概念说:

    每个线程都有一个“信号掩码”,用于定义当前阻止传递给它的信号集。

    应用于您的代码片段

    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.

     
    粤ICP备18138465号  © 2020-2024 STACKOOM.COM