【问题标题】:sigaction : using "void (*sa_sigaction)(int, siginfo_t *, void *);"sigaction:使用“void (*sa_sigaction)(int, siginfo_t *, void *);”
【发布时间】:2017-07-03 07:13:31
【问题描述】:

sigaction 联机帮助页中写道:

sa_sigaction 还指定要与signum 关联的操作。 这个函数接收信号编号作为它的第一个参数,a 指向 siginfo_t 的指针作为其第二个参数和指向 ucon- text_t(转换为void*)作为其第三个参数。

所以我们可以将参数传递给信号处理程序(通过void*),但我 找不到路。 有没有办法把它放在任何地方?

例子:

struct ping_val
{
    int data1;
    int data2;
};

void ping(int sig, siginfo_t *siginf, void *ptr) 
{
    // ....
}

int main()
{
    struct sigaction sa_ping;
    ping_val foo;
    foo.data1 = 3;
    foo.data2 = 4;
    sa_ping.sa_sigaction = ping;
    sigemptyset(&sa_ping.sa_mask);
    sa_ping.sa_flags = 0;
    sigaction(SIGALRM, &sa_ping, NULL);
    // ....
}

在哪里我可以在 ping 的参数中传递 foo 结构值(在 struct * 中进行转换)???

【问题讨论】:

  • 不,您不能将任意数据传递给信号处理程序。您只能控制sigaction 结构,它没有用户数据字段。此外,对于要调用的信号函数的三参数变体,您必须指定SA_SIGINFO 标志。
  • 你的困惑可能来自ucontext_t这个名字中的u?它不代表“用户数据”,它是导致信号的线程堆栈帧的结构。

标签: c++ c pointers struct signals


【解决方案1】:

您不能将任何参数传递给信号处理程序,因为您从不自己调用它。一个信号处理程序被操作系统调用,它对你的参数一无所知。

让信号处理程序与主程序通信的标准方法是通过全局(或文件范围)变量。

【讨论】:

    【解决方案2】:

    信号处理程序接收的siginfo_t 结构包含union sigval si_value 成员:

    union sigval {
        int    sival_int; // Integer signal value 
        void  *sival_ptr; // Pointer signal value 
    }
    

    因此,如果您在单个进程内(或者在某些情况下,在分叉之间)发送信号,您可以发送指向某些数据的指针。

    我知道将sigval 值发送到信号处理程序的两种方法:

    如果您使用timer_create 创建一个计时器,您需要传递一个sigevent 结构,其中包含一个union sigval sigev_value 成员。按照惯例,用户代码会将sigev_value.sival_ptr 设置为定时器ID,以便信号处理程序在必要时区分多个定时器,但您可以将其设置为任何void * 值。

    如果您使用sigqueue(而不是killraise、故障等)发送信号,您可以给它一个union sigval 作为参数。

    【讨论】:

      【解决方案3】:

      你写:

      所以我们可以[通过 void* ucontext_t 参数] 将参数传递给信号处理程序,但我找不到方法。

      找不到这样的方法——ucontext_t 参数由系统自己设置并引用 "the receiving thread's context that was interrupted when the signal was delivered."

      (具体来说,by spec 它至少包含对该中断上下文的引用,以及对该上下文的机器特定表示,以及当前上下文的堆栈及其阻塞信号集。)

      您可能不需要任何这些。如果您希望您的程序在收到信号时采取一些行动和/或修改其状态,那么您可以在信号处理程序中安全使用的策略数量有限(volatile sigatomic_t flags, self-pipes, platform-specific interfaces),但是您的主循环可以当然,只要知道刚刚收到 SIGFOO,就可以为所欲为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多