UNIX/Linux 信号处理:SIGEV_THREAD

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5153972/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:04:43  来源:igfitidea点击:

UNIX/Linux signal handling: SIGEV_THREAD

clinuxunixposixsignals

提问by kingsmasher1

I have put a simple signal handler in my code. I have initialised the sigevent structure, with a handler function to catch the signal.

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

Can someone please pin-point as to why the code is not working? Ideally if there is a signal, my handler should be called. But it is not.

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

Please help me, Thanks Kingsmasher1

请帮助我,谢谢 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
}

采纳答案by caf

struct sigeventis not about specifying how the process will handle a signal - struct sigactionand sigaction()are how you do that. Instead, struct sigeventis used to specify how your process will be informed of some asychronous event - like the completion of asychronous IO, or a timer expiring.

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

The sigev_notifyfield specifies how the event should be notified:

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

  • SIGEV_NONE- no notification at all. The remainder of the fields are ignored.
  • SIGEV_SIGNAL- a signal is sent to the process. The sigev_signofield specifies the signal, the sigev_valuefield contains supplementary data that is passed to the signal handling function, and the remainder of the fields are ignored.
  • SIGEV_THREAD- a function is called in a new thread. The sigev_notify_functionfield specifies the function that is called, sigev_valuecontains supplementary data that is passed to the function, and sigev_notify_attributesspecifies thread attributes to use for the thread creation. The remainder of the fields are ignored.
  • SIGEV_NONE- 根本没有通知。其余字段将被忽略。
  • SIGEV_SIGNAL- 向进程发送信号。该sigev_signo字段指定信号,该sigev_value字段包含传递给信号处理函数的补充数据,其余字段将被忽略。
  • SIGEV_THREAD- 在新线程中调用函数。该sigev_notify_function字段指定被调用的函数,sigev_value包含传递给函数的补充数据,并sigev_notify_attributes指定用于创建线程的线程属性。其余字段将被忽略。

Note in particular that if you set SIGEV_THREAD, the sigev_signofield is ignored - the struct sigeventis about specifying eithera thread or a signal as a notification method, not about specifying a thread as the way that a signal should be handled.

请特别注意,如果你设置SIGEV_THREAD,该sigev_signo字段被忽略-struct sigevent是关于指定任何一个线程或信号的通知方法,不是指定一个线程中的信号应该处理方式。

The struct sigeventmust also be passed to a function - like timer_create()- that sets up the asychronous event that will be notified. Simply creating a struct sigeventobject does not do anything special.

struct sigevent还必须传递给函数-像timer_create()- ,设置了将被通知台异步事件。简单地创建一个struct sigevent对象并没有做任何特别的事情。

If you wish to use a dedicated thread to handle a signal, create the thread up front and have it loop around, blocking on sigwaitinfo(). Use sigprocmask()to block the signal in every other thread.

如果您希望使用专用线程来处理信号,请预先创建线程并使其循环,阻塞在sigwaitinfo(). 用于sigprocmask()在每个其他线程中阻止信号。

回答by Hymanson

I think you are mixing up your signal handling idioms here, you create a sigeventstructure and then do nothing with it and then use signal()within the signal handler. The following code shows a very simple signal handling routine based on your code; note that I have changed the definition of my_handler. If you need more sophisticated handling then sigaction()is probably the system call you need to look into.

我认为你在这里混淆了你的信号处理习惯用法,你创建了一个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!
}

This works under cygwinon my windows box (no access to a linux box at the minute).

这适用cygwin于我的 windows 机器(目前无法访问 linux 机器)。

回答by Suganthan Sundaram

I hope this works.

我希望这有效。

#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");
}