2011-03-01 230 views
4

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

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

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

回答

13

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_THREAD,该sigev_signo字段被忽略 - struct sigevent是有关指定要么螺纹或信号的通知方法,不是指定线程的方式,一个信号应该处理。

struct sigevent还必须传递给一个函数,如timer_create(),它设置了将被通知的异步事件。简单地创建一个struct sigevent对象不会做任何特殊的事情。

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

2

我觉得你在这里混淆了你的信号处理成语,为您营造的sigevent结构,然后什么也不做它,然后将信号中使用的信号()处理程序。以下代码显示了基于您的代码的非常简单的信号处理例程;注意我已经改变了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! 
} 

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系统)。

+0

但是,OP对'sigevent' **没有做任何事情**在逻辑上必须是问题,所以+1。 – 2011-03-01 11:54:06

+0

这是我知道的方法,但我想使用sigevent并使用SIGEV_THREAD来调用该函数。如果你能以这种方式帮助我,那将会很棒 – kingsmasher1 2011-03-01 12:16:00

+0

通过简单的拖网通过文档,你所得到的问题是,sigevent是关于事件处理而不是信号处理。这听起来像你想在你的进程接收到SIGRTMIN信号时在新线程中调用信号处理程序,而sigevent用于async io(请参阅aio手册页)。您需要查看signal()的文档,并且您的操作系统是否支持sigaction()以查看您可以执行的操作。 – Jackson 2011-03-01 15:30:40

0

我希望这有效。

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