POSIX(Portable Operating System Interface )信号处理


信号

信号(signal)就是可知某个进程发生了某个事件的通知,有时也称为软件中断(software interruption)。

信号通常是异步发生的。

信号可以:

*由一个进程发给另一个进程(或自身)

*由内核发给某个进程

每个信号都有一个与之关联的处置(disposition),也称为行为(action)。

通过sigaction函数来设定一个信号的处置,有三种选择:

(1)信号发生时调用信号处理函数(signal handler),即捕获(catching)信号,

        其中,SIGKILL,SIGSTOP两个信号无法被捕捉。

        函数原型:void handler(int signo);
(2)通过设置信号处理办法为SIG_ING来忽略信号,

        其中,SIGKILL,SIGSTOP无法被忽略。
(3)通过设置信号处理办法为SIG_DFL来设置信号的默认处置方法,

        默认处置通常是早收到信号后终止进程,个别信号的默认处置是忽略。

signal函数

建立信号处置的POSIX方法就是调用sigaction函数。简单的方法是用signal函数,它的第一个参数是信号名,第二个参数是指向函数的指针或为常值SIG_DFL或SIG_IGN。

由于历史原因,signal在各种平台上的实现可能会不尽相同,而POSIX明确规定调用sigaction函数的语义,但sigaction函数调用往往比较复杂,解决方法是用sigaction实现自己的signal函数,signal函数原型:

void (*signal(int signo, void (*handle)(int)))(int);

其中signal接受两个参数,一个int型的信号编码,另一个处理信号的函数指针,

然后返回一个之前定义的处理信号的函数的指针,处理函数接受一个int型参数,返回void,这样看起来挺麻烦的,简单点可以这样定义:

typdef void (SIG_HANDLE)(int);
SIG_HANDLE *signal(int, SIG_HANDLE *);

好了,知道了signal的基本语义了,现在可以用sigaction实现它了,代码如下:

  1. #include <signal.h>   
  2.   
  3. /*  
  4. * 用sigaction实现signal  
  5. */  
  6.   
  7. typedef void (SIG_PROC)(int);   
  8.   
  9. SIG_PROC *_signal(int signo, SIG_PROC *sig_proc)   
  10. {   
  11. struct sigaction act;   
  12. struct sigaction oact;   
  13.   
  14. act.sa_handler = sig_proc;   
  15. // 设置信号处理函数的信号掩码:信号处理函数调用期间,除屏蔽本信号外,不阻塞其他信号,   
  16. // 信号处理函数执行完毕后,信号屏蔽字恢复到之前的值   
  17. sigemptyset(&act.sa_mask);   
  18. act.sa_flags = 0;   
  19.   
  20. // 除了SIGALRM以外的其他信号,如果被中断都将尝试重新启动(linux下)   
  21. if (signo == SIGALRM)   
  22. {  
  23. #ifdef SA_INTERRUPT   
  24. act.sa_flags |= SA_INTERRUPT;  
  25. #endif   
  26. }   
  27. else  
  28. {  
  29. #ifdef SA_RESTART   
  30. //如果设置了restart,内核将重启被中断的系统调用,系统调用不会返回-1   
  31. act.sa_flags |= SA_RESTART;  
  32. #endif   
  33. }   
  34.   
  35. if (sigaction(signo, &act, &oact) < 0)   
  36. {   
  37. return SIG_ERR;   
  38. }   
  39. return oact.sa_handler;   
  40. }  

相关内容