sigaction:使用“void(* sa_sigaction)(int,siginfo_t *,void *);”

时间:2017-07-03 07:13:31

标签: c++ c pointers struct signals

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 *中使用强制转换)???

3 个答案:

答案 0 :(得分:0)

您不能将任何参数传递给信号处理程序,因为您自己从不调用它。操作系统调用信号处理程序,它不了解您的参数。

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

答案 1 :(得分:0)

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

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

因此,如果您在单个进程中(或在某些情况下,在某些情况下,我认为是forks)中发送信号,您可以发送指向某些数据的指针。

我知道有两种方法可以将sigval值发送给信号处理程序:

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

如果您使用sigqueue(而不是killraise,错误等)来发送信号,则会给它一个union sigval作为参数。

答案 2 :(得分:0)

你写道:

  

所以我们可以将参数传递给信号处理程序[通过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刚收到的知识做任何你想做的事。