【问题标题】:UNIX/Linux signal handling: SIGEV_THREADUNIX/Linux 信号处理:SIGEV_THREAD
【发布时间】:2011-03-01 11:37:54
【问题描述】:

我在我的代码中放置了一个简单的信号处理程序。我已经初始化了 sigevent 结构,并使用一个处理函数来捕获信号。

有人可以指出为什么代码不起作用吗?理想情况下,如果有信号,应该调用我的处理程序。但事实并非如此。

请帮帮我, 谢谢 Kingsmasher1

enter code here
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>

void my_handler(int sival_int, void* sival_ptr)
{
 printf("my_handler caught\n");
 signal(sig,my_handler);
}

int main()
{
 struct sigevent sevp;

 sevp.sigev_notify=SIGEV_THREAD;
 sevp.sigev_signo=SIGRTMIN;
 sevp.sigev_value.sival_ptr=NULL;
 sevp.sigev_notify_function=(void*)my_handler;
 kill(0,SIGRTMIN); // This should invoke the signal and call the function
}

【问题讨论】:

    标签: c linux unix posix signals


    【解决方案1】:

    struct sigevent 不是指定进程将如何处理信号 - struct sigactionsigaction() 是你这样做的方式。相反,struct sigevent 用于指定如何将某些异步事件通知您的进程 - 例如异步 IO 完成或计时器到期。

    sigev_notify 字段指定应如何通知事件:

    • SIGEV_NONE - 根本没有通知。其余字段将被忽略。
    • SIGEV_SIGNAL - 向进程发送信号。 sigev_signo 字段指定信号,sigev_value 字段包含传递给信号处理函数的补充数据,其余字段将被忽略。
    • SIGEV_THREAD - 在新线程中调用函数。 sigev_notify_function 字段指定调用的函数,sigev_value 包含传递给函数的补充数据,sigev_notify_attributes 指定用于创建线程的线程属性。其余字段将被忽略。

    请特别注意,如果您设置SIGEV_THREADsigev_signo 字段将被忽略 - struct sigevent 是关于指定一个线程或一个信号作为通知方法,而不是指定一个线程作为处理信号的方式。

    struct sigevent 还必须传递给一个函数——比如timer_create()——它设置了将被通知的异步事件。简单地创建一个struct sigevent 对象并没有什么特别的。

    如果您希望使用专用线程来处理信号,请在前面创建线程并让它循环,在sigwaitinfo() 上阻塞。使用sigprocmask() 阻止其他线程中的信号。

    【讨论】:

      【解决方案2】:

      我认为你在这里混淆了你的信号处理习惯用法,你创建了一个 sigevent 结构,然后什么都不做,然后在信号处理程序中使用 signal()。以下代码显示了一个基于您的代码的非常简单的信号处理例程;请注意,我更改了my_handler 的定义。如果您需要更复杂的处理,那么sigaction() 可能是您需要研究的系统调用。

      #include <stdlib.h>
      #include <unistd.h>
      #include <stdio.h>
      #include <signal.h>
      #include <time.h>
      
      void my_handler(int sig)
      {
       printf("my_handler caught\n");
       signal(sig,my_handler);
      }
      
      int main()
      {
       signal(SIGRTMIN,my_handler);
       kill(0,SIGRTMIN); // This should invoke the signal and call the function
       while(1) ;  // Infinite loop in case the program ends before the signal gets caught!
      }
      

      这在我的 windows 机器上的 cygwin 下工作(目前无法访问 linux 机器)。

      【讨论】:

      • 但是 OP 没有对 sigevent 做任何事情 必须在逻辑上是问题所在,所以 +1。
      • 我知道这种方法,但我想使用 sigevent 并使用 SIGEV_THREAD 来调用该函数。如果你能以这种方式帮助我,那就太好了
      • 从对文档的简短搜索中,您遇到的问题是 sigevent 是关于事件处理而不是关于信号处理。听起来您想在进程接收到 SIGRTMIN 信号时在新线程中调用信号处理程序,而 sigevent 用于诸如异步 io 之类的事情(请参阅 aio 手册页)。您需要查看 signal() 的文档以及您的操作系统是否支持 sigaction() 以了解您可以做什么。
      【解决方案3】:

      我希望这行得通。

      #include <stdlib.h>
      #include <unistd.h>
      #include <stdio.h>
      #include <signal.h>
      #include <time.h>
      
      void
      my_handler (int sig)
      {
          printf ("my_handler caught\n");
          signal (sig, my_handler);
      }
      
      int
      main ()
      {
          int signo;
          struct sigevent sevp;
          sigset_t set;
      
          if (sigemptyset (&set) == -1)
              perror ("sigemptyset");
          if (sigaddset (&set, SIGRTMIN) == -1)
              perror ("sigaddset");
          if (sigprocmask (SIG_BLOCK, &set, NULL) == -1)
              perror ("sigprocmask");
      
           sevp.sigev_notify = SIGEV_THREAD;
           sevp.sigev_signo = SIGRTMIN;
           sevp.sigev_value.sival_ptr = NULL;
           kill (0, SIGRTMIN);
           if (sigwait (&set, &signo) == 0)
               my_handler (signo);
           else
               perror ("sigwait");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-28
        • 1970-01-01
        • 1970-01-01
        • 2012-04-30
        • 2016-03-31
        • 2021-05-19
        • 1970-01-01
        相关资源
        最近更新 更多