Linux 执行默认信号处理程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6015498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 04:06:07  来源:igfitidea点击:

executing default signal handler

clinuxsignalshandlers

提问by app

I have written an application where i have registered number of signal handler for different signals in linux . After process receives the signal the control is transferred to the signal handler i had registered. In this signal handler i do some work which i need to do, and then i would like to call the default signal hander i.e SIF_DFLor SIG_IGN. However, SIG_DFLand SIG_INGare both macros which expand to numeric values 0 and 1 respectively, which are invalid function addresses.

我写了一个应用程序,我在 linux 中为不同的信号注册了信号处理程序的数量。进程收到信号后,控制权被转移到我注册的信号处理程序。在这个信号处理程序中,我做了一些我需要做的工作,然后我想调用默认的信号处理程序 ieSIF_DFLSIG_IGN. 但是,SIG_DFLSIG_ING都是分别扩展为数值 0 和 1 的宏,它们是无效的函数地址。

IS there any way i can call default actions i.e SIG_DFLor SIG_IGN?

有什么办法可以调用默认操作 ieSIG_DFLSIG_IGN吗?

In order to achieve the effect of SIG_DFLor SIG_INGi call exit(1) and do nothing , respectively . But for signals like SIGSEGVi also would like to have core dump . In general i would want to my default behavior to be same as SIG_DFLand ignore behavior same SIG_IGN, the way Operating system would do .

为了达到SIG_DFLor的效果, SIG_ING我分别调用 exit(1) 和什么都不做。但是对于像SIGSEGV我这样的信号,我也想要核心转储。一般来说,我希望我的默认行为与操作系统SIG_DFL相同SIG_IGN,并忽略相同的行为。

回答by Jan Hudec

Given the signal handlers are implemented in kernel, the only way I see is to

鉴于信号处理程序是在内核中实现的,我看到的唯一方法是

  • reset the handler and
  • raise()the signal again
  • 重置处理程序和
  • raise()又是信号

回答by Philip

The usual approach is to reset the signal handler and then raise()the signal again:

通常的方法是重置信号处理程序,然后raise()再次重置信号:

Here's an example SIGINT handler:

这是一个示例 SIGINT 处理程序:

void sigint_handler(int num)
{
    /* handle SIGINT */

    // call default handler
    signal(SIGINT, SIG_DFL);
    raise(SIGINT);
}

回答by cnicutar

You can save the previous handler and then call it when the time is right.

您可以保存之前的处理程序,然后在适当的时候调用它。

Install handler. Make sure you save old handler

安装处理程序。确保您保存旧处理程序

static struct sigaction new_sa, old_sa;

new_sa.sa_handler = my_handler;
sigemptyset(&new_handler.sa_mask);

if (sigaction(signo, &new_sa, &old_sa) == -1) {
    /* handle sigaction error */
}

In your new handler, call the old handler

在您的新处理程序中,调用旧处理程序

(*old_sa.sa_handler)(signo)

You don't need to raise it again or do any messy stuff; simply call the old handler (of course, since you saved the sigactionyou have acces to the old disposition and so on).

你不需要再次提出它或做任何乱七八糟的事情;只需调用旧处理程序(当然,因为您保存了sigaction您可以访问旧处理程序等)。

回答by homac

The GNU C Library Reference Manualhas a whole chapter explaining everything about signal handling.

GNU C 库参考手册有一整章解释了有关信​​号处理的所有内容。

You always get the previously set signal handler (a function pointer) when you install your own handler (see manpages for signal()or sigaction()).

当您安装自己的处理程序时,您总是会获得先前设置的信号处理程序(一个函数指针)(请参阅signal()或 的联机帮助页sigaction())。

previous_handler = signal(SIGINT, myhandler);

The general rule is, that you can always reset to the previous handler and raise()the signal again.

一般规则是,您始终可以重置为先前的处理程序和raise()再次发出信号。

void myhandler(int sig) {
  /* own stuff .. */
  signal(sig, previous_handler);
  raise(sig);
  /* when it returns here .. set our signal handler again */
  signal(sig, myhandler);
}

There is one disadvantageof the general rule: Hardware exceptions which are mapped to signals are usually assigned to a certain instruction which caused the exception. So, when you raise a signal again, the associated instruction is not the same as originally. This can but should not harm other signal handlers.

一般规则有一个缺点:映射到信号的硬件异常通常分配给导致异常的特定指令。因此,当您再次发出信号时,关联的指令与原始指令不同。这可以但不应该损害其他信号处理程序。

Another disadvantageis, that each raised signal causes a lot of processing time. To prevent excessive use of raise()you can use the following alternatives:

另一个缺点是,每个升高的信号都会导致大量的处理时间。为了防止过度使用,raise()您可以使用以下替代方法:

  1. In case of SIG_DFLthe function pointer points to address 0(which is obviously no valid address). Thus, you have toreset the handler and raise()the signal again.

    if (previous_handler == SIG_DFL)
    {
      signal(sig, SIG_DFL);
      raise(sig);
      signal(sig, myhandler);
    } 
  2. SIG_IGNhas value 1(also an invalid address). Here you can just return (do nothing).

    else if (previous_handler == SIG_IGN)
    {
      return;
    } 
  3. Otherwise (neither SIG_IGNnor SIG_DFL) you have received a valid function pointer and you cancall the handler directly,

    else
    {
      previous_handler(sig);
    }
  1. 如果SIG_DFL函数指针指向地址0(显然不是有效地址)。因此,您必须再次重置处理程序和raise()信号。

    if (previous_handler == SIG_DFL)
    {
      signal(sig, SIG_DFL);
      raise(sig);
      signal(sig, myhandler);
    } 
  2. SIG_IGN有值1(也是无效地址)。在这里你可以直接返回(什么都不做)。

    else if (previous_handler == SIG_IGN)
    {
      return;
    } 
  3. 否则(既不是SIG_IGN也不是SIG_DFL)您收到了有效的函数指针,您可以直接调用处理程序,

    else
    {
      previous_handler(sig);
    }

Of course, you have to consider the different APIs as well (see manpages for signal()and sigaction()).

当然,您还必须考虑不同的 API(请参阅signal()和 的联机帮助页sigaction())。