我编写了一个应用程序,我在其中为 linux 中的不同信号注册了多个信号处理程序。
进程收到信号后,控制权将转移到我注册的信号处理程序。在这个信号处理程序中,我做了一些我需要做的工作,然后我想调用默认信号处理程序,即 SIF_DFL
或 SIG_IGN
。
但是,SIG_DFL
和SIG_ING
都是宏,分别扩展为数值0和1,是无效的函数地址。
有什么方法可以调用默认操作,即 SIG_DFL
或 SIG_IGN
吗?
为了实现 SIG_DFL
或 SIG_ING
的效果,我分别调用了 exit(1) 并且什么都不做。但是对于像 SIGSEGV
这样的信号,我也希望有 core dump 。
一般来说,我希望我的默认行为与 SIG_DFL
相同,并忽略与 SIG_IGN
相同的行为,操作系统会这样做。
最佳答案
The GNU C Library Reference Manual有一整章解释有关信号处理的一切。
当您安装自己的处理程序时(请参阅signal()
或sigaction()
的联机帮助页),您总是会获得先前设置的信号处理程序(函数指针)。
previous_handler = signal(SIGINT, myhandler);
一般规则是,您始终可以重置为之前的处理程序并再次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);
}
通用规则有一个缺点:映射到信号的硬件异常通常分配给导致异常的特定指令。因此,当您再次发出信号时,关联的指令与原来的指令不同。这可以但不应该损害其他信号处理程序。
另一个缺点是,每个发出的信号都会导致大量处理时间。为防止过度使用 raise()
,您可以使用以下替代方法:
在
SIG_DFL
的情况下,函数指针指向地址0
(这显然不是有效地址)。因此,您必须重置处理程序并再次raise()
信号。if (previous_handler == SIG_DFL) { signal(sig, SIG_DFL); raise(sig); signal(sig, myhandler); }
SIG_IGN
的值为1
(也是无效地址)。在这里你可以返回(什么都不做)。else if (previous_handler == SIG_IGN) { return; }
否则(既不是
SIG_IGN
也不是SIG_DFL
)您收到了一个有效的函数指针并且您可以直接调用处理程序,else { previous_handler(sig); }
当然,您还必须考虑不同的 API(请参阅 signal()
和 sigaction()
的联机帮助页)。
关于c - 执行默认信号处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6015498/