忽略信号的不同方法?

different ways to ignore a signal?

我是 Linux 和信号处理的新手。 signal 函数原型是

sighandler_t signal(int signum, sighandler_t handler);

以下是我的问题:

Q1-如果我想忽略SIGINT信号,那么我只需要简单地编码为: signal(SIGINT, SIG_IGN);,我的理解对吗?

Q2-如果我编码为:

void sigint_handler(int sig) 
{
   //do thing
}

int main() 
{
    /* Install the SIGINT handler */         
    if (signal(SIGINT, sigint_handler) == SIG_ERR)  
       unix_error("signal error");                
    
    pause(); /* Wait for the receipt of a signal */  
    
    return 0;
}

由于我自己的 sigint_handler 什么都不做,这几乎就像忽略了 SIGINT,所以我可以说这种方法与 signal(SIGINT, SIG_IGN); 基本相同吗?

Q3-SIG_IGN 在哪里?是否在用户进程地址space中的.code段为:

如果我的假设是正确的,编译器会自动将此处理程序注入编译后的代码吗?

Q3。 SIG_DFLSIG_IGNSIG_ERR 不是实函数。它们是 signal() 专门处理的常量。具体来说,在 Linux 上,SIG_DFL 具有整数值 1SIG_IGN 具有整数值 0SIG_ERR 具有整数值 -1 , none 其中是有效的函数指针。

Q2。不,自定义信号处理程序(即使 no-op)的行为与 SIG_IGN 略有不同。如果您调用 exec(),处置 SIG_IGN 的信号将被继承,而所有其他信号将重置为 SIG_DFL([=24= 除外],其中 POSIX 没有指定应该是 SIG_IGNSIG_DFL).

Q1。是的,但即使 这种 情况无关紧要,一般情况下更喜欢使用 sigaction() 而不是 signal()

if I want to ignore SIGINT signal, then I just need to simply code as: signal(SIGINT, SIG_IGN);, is my understanding corrct?

是的,但是 signal 的文档建议使用 sigactionsignal 的语义因系统而异,而 sigaction 的语义更一致。

does the compiler automacially inject this handler into the compiled code?

没有。编译器不会为 SIG_IGN 创建空处理程序。它从字面上告诉 OS 忽略进程的信号。它不是一个函数指针,而是一个 signal 特殊处理的值。

since my own sigint_handler does nothing, it is pretty much like ignoring the SIGINT, so can I say this approach is fundamentally the same as signal(SIGINT, SIG_IGN);?

虽然两者都有效地忽略了信号,但还是有区别的。

  • 使用信号处理程序时,阻塞系统调用可能 return 过早出现错误 EINTR 以允许信号处理程序 运行。 SIG_IGN.
  • 不会发生这种情况
  • SIG_IGN 将存活 exec,但处理程序不会。
  • 在某些系统上,当调用信号处理程序时,信号的配置会重置为 SIG_DFL,因此您的代码只会忽略此类系统上信号的第一个实例。
  • 还有其他差异,可能因平台而异。