本文介绍了需要 sigsuspend 的说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要澄清 sigsuspend 主题.我有一个简化的例子

sigset_t 掩码,旧掩码;sigemptyset (&mask);sigaddset (&mask, SIGRTMIN+1);sigprocmask (SIG_BLOCK, &mask, &oldmask);sigsuspend(&oldmask);sigprocmask (SIG_UNBLOCK, &mask, NULL);

我是这么理解的:

  • sigemptyset 清除信号列表(掩码)——因为它是用当前阻塞的信号(?)
  • sigaddset 添加 SIGRTMIN+1 到掩码
  • sigprocmask 将 mask+oldmask 中的所有信号设置为阻塞
  • sigsuspend(&oldmask) 暂停线程执行直到阻塞信号之一到达?想屏蔽SIGRTMIN+1不应该有sigsuspend(&mask)吗?

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

    while(1){sigsuspend(&oldmask)printf("收到信号");}

    这样对于每个信号我都打印了收到的信号"?

    解决方案

    POSIX 对 sigsuspend()

    的定义

    POSIX 标准描述了 sigsuspend() 相当清楚:

    #include

    int sigsuspend(const sigset_t *sigmask);

    描述

    sigsuspend() 函数应将调用线程的当前信号掩码替换为 sigmask 指向的一组信号,然后挂起线程直到传递其动作是执行信号捕获功能或终止进程的信号.这不会导致任何其他可能在进程上挂起的信号在线程上挂起.

    如果操作是终止进程,则 sigsuspend() 将永远不会返回.如果动作是执行一个信号捕捉函数,那么sigsuspend()应在信号捕捉函数返回后返回,信号掩码恢复到sigsuspend之前存在的集合() 调用.

    无法阻止无法忽略的信号.这是由系统强制执行的,不会导致指示错误.

    返回值

    由于 sigsuspend() 无限期地暂停线程执行,所以没有成功完成返回值.如果发生返回,则返回 -1 并设置 errno 以指示错误.

    错误

    sigsuspend() 函数将在以下情况下失败:

    [EINTR]调用进程捕获一个信号,并从信号捕获函数返回控制权.

    此外,POSIX 信号概念说:>

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

    应用到您的代码片段

    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,那么您的信号将在您的代码处于 &oldmask代码>sigsuspend().

    您对sigprocmask()的描述 不正确:

    当你这样做时:

    sigset_t 掩码,旧掩码;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 中的 not 信号之一.oldmask 的内容是在你添加 SIGRTMIN+1 之前被阻塞的一组信号.

    绝对不会!这将挂起线程,直到 mask 中的 not 信号之一到达.由于 mask 中唯一的信号是 SIGRTMIN+1,因此只有该信号被阻塞,当任何其他信号到达时,它将被处理并且 sigsuspend() 将返回.sigprocmask() 报告了在oldmask 中调用之前被阻塞的内容;它根本没有修改 mask (你的变量);它确实通过添加 SIGRTMIN+1 修改了进程的信号掩码.

    我强烈建议阅读或重读 POSIX 信号概念 以及操纵信号处理的各种函数.(是的,这部分是医生,治愈你自己"的处方.)

    如果这里还有错误,请告诉我.

    I need a clarification on sigsuspend topic.I have a simplified example

    sigset_t mask, oldmask;
    sigemptyset (&mask);
    sigaddset (&mask, SIGRTMIN+1);
    sigprocmask (SIG_BLOCK, &mask, &oldmask);
    
    sigsuspend(&oldmask);
    
    sigprocmask (SIG_UNBLOCK, &mask, NULL);
    

    Here is how I understand this:

  • sigemptyset clears a list of signals (mask) - because it is initialized with currently blocked signals (?)
  • sigaddset adds SIGRTMIN+1 to mask
  • sigprocmask sets all signals in mask+oldmask to be blocked
  • sigsuspend(&oldmask) suspends thread execution till one of the blocked signals arrives ? Shouldn't there be sigsuspend(&mask) if I want to block SIGRTMIN+1?

    Secondly, let's suppose I have such sigsuspend in a loop and there arrived a few SIGRTMIN+1 signals. Will such loop continue for each signal ? in some kind of queue?

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

    so that for each signal I have 'recieved signal' printed?

    解决方案

    POSIX's definition of sigsuspend()

    The POSIX standard describes sigsuspend() fairly clearly:

    Also, the POSIX Signal concepts says:

    Application to your code fragments

    The sigsuspend() function is the modern analogue of the old pause() function.

    It allows you to send your thread to sleep until one of its selected signals occurs. If you want it to sleep until SIGRTMIN+1 arrives, you use:

    sigfillset(&mask);
    sigdelset(&mask, SIGRTMIN+1);
    sigsuspend(&mask);
    

    This blocks every signal except SIGRTMIN+1.

    If you want to sleep until a signal other than SIGRTMIN+1 arrives, you use:

    sigemptyset(&mask);
    sigaddset(&mask, SIGRTMIN+1);
    sigsuspend(&mask);
    

    This blocks only SIGRTMIN+1.

    Your loop won't print Received signal reliably unless you add a newline at the end (and maybe not even then; you might need to fflush(stdout) or equivalent). However, if you have SIGRTMIN+1 blocked in the ordinary course of events and then you set up &oldmask to allow only SIGRTMIN+1, then your signals will be reliably delivered while your code is in sigsuspend().

    Your description of sigprocmask() is not correct:

    Yes, it is wrong. Calling sigsuspend(&oldmask) sends your thread to sleep until one of the signals not in oldmask is received. The content of oldmask is the set of signals that was blocked before you added SIGRTMIN+1.

    Absolutely not! This will suspend the thread until one of the signals not in mask arrives. Since the only signal in mask is SIGRTMIN+1, only that signal is blocked and when any other signal arrives, it will be handled and sigsuspend() will return. The sigprocmask() reported what was being blocked before the call in oldmask; it did not modify mask (your variable) at all; it did modify the process's signal mask by adding SIGRTMIN+1.


    I strongly recommend reading, or rereading, the POSIX Signal concepts and the various functions that manipulate signal handling. (And yes, this is, in part, a prescription of "Physician, heal thyself".)

    Please let me know if there are still mistakes in here.

    这篇关于需要 sigsuspend 的说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

  • 10-20 15:38