【问题标题】:Can we send parameters to a signal handler using sigaction?我们可以使用 sigaction 将参数发送到信号处理程序吗?
【发布时间】:2020-06-03 15:06:36
【问题描述】:

我注意到 sigaction 有一个备用信号处理程序,当设置 SA_SIGINFO 标志时会调用该处理程序。备用函数有一个 void* context 参数。现在,根据APUE一书,这个参数可以转换成ucontext_t结构。我的问题是,我不能将其转换为我选择的任何结构吗?这样我就可以将自己的参数传递给信号处理程序。我注意到 stackoverflow 中有一篇文章指出我们不能将参数传递给信号处理程序,因为它们是一个非常原始的特性。这可能吗 ?

【问题讨论】:

    标签: c linux signals signal-handling signalhandler


    【解决方案1】:

    是的,您可以将用户提供的数据传递给信号处理程序 - 但不能使用 context 参数。相反,您必须使用sigqueue(3) 来通过使用SA_SIGINFO 安装的处理程序引发信号。这将填充作为处理程序第二个参数的siginfo_t 结构的si_int 或si_ptr 字段,具体取决于sigqueue() 的第三个参数。

    例子:

    #include <signal.h>
    #include <string.h>
    #include <unistd.h>
    
    void usr1_handler(int signo, siginfo_t *info, void *context) {
      const char *msg = info->si_ptr;
      write(STDOUT_FILENO, msg, strlen(msg));
    }
    
    int main(void) {
      struct sigaction sa;
      sa.sa_sigaction = usr1_handler;
      sigemptyset(&sa.sa_mask);
      sa.sa_flags = SA_SIGINFO;
      sigaction(SIGUSR1, &sa, NULL);
    
      const char *msg = "SIGUSR1 was called.\n";
      sigqueue(getpid(), SIGUSR1, (union sigval){ .sival_ptr = (void *)msg });
    
      return 0;
    }
    

    (当然,真正的代码将包括错误检查和处理)。

    编译运行后,这个玩具程序将打印SIGUSR1 was called.。

    【讨论】:

      【解决方案2】:

      来自this sigaction manual page:

      这是一个指向 ucontext_t 结构的指针,转换为 void *。该字段指向的结构包含由内核保存在用户空间堆栈中的信号上下文信息; ... 通常,处理函数不使用第三个参数。

      所以这个参数是一个特定于内核的指针,指向一个特殊的信号上下文。无法将其重用于用户数据。

      【讨论】:

      • 不过,是一种将用户数据传递给信号处理程序的方法。看我的回答。
      【解决方案3】:

      关于将参数传递给信号处理程序,我注意到的另一件重要的事情是,能够将附加参数传递给信号处理程序的整个概念没有任何意义。信号处理程序是程序员没有明确调用的东西。相反,当内核向程序发送信号时,它会被异步调用。现在,即使可以将额外的参数传递给信号处理程序,什么会确定要发送哪个参数?假设信号处理程序的原型为 void func(int, void*);。应用程序如何知道应该将哪个参数传递给第二个参数?这将是一个完全不确定的情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多