signal函数和sigactiion函数的对比

来源:互联网 发布:赵敏 张无忌的爱情知乎 编辑:程序博客网 时间:2024/05/16 10:34

在《UNIX环境高级编程》中,作者写道:从UNIX System V派生的实现支持signal函数,但该函数提供旧的不可靠的语义,4.4BSD也提供signal函数,但它是按照sigaction函数定义的,所以在4.4BSD之下使用它提供新的可靠信号语义,目前大多数系统遵循这种策略。

在该书10.4节,作者举了两个不可靠信号的例子。一是如下代码,目的是不要调用一次信号处理函数之后就回到默认动作,而是一直使用该信号处理函数处理信号。但是问题是,在信号发生之后到信号处理程序调用signal之间的时间窗内有可能再次发生信号,第二次发生的信号会执行默认动作而不是注册的信号处理函数。

int sig_int();...signal(SIG_INT_, sig_int);...sig_int(){<span style="white-space:pre"></span>signal(SIG_INT, sig_int);<span style="white-space:pre"></span>...}

二是进程无法关闭信号而只能忽略它,使用标志位来处理,代码格式如下。但是在测试标志位和调用pause()的时间窗中,发生信号的话就会造成pause()永久休眠,因此也是不可靠的。

int sig_int();int sig_int_flag;main(){    signal(SIGINT, sig_int);    ...    while(sig_int_flag == 0)        pause();    ...}sig_int(){    signal(SIGINT, sig_int);    sig_int_flag = 1;}

而sigaction可以避免这个问题,因而是可靠的。一般都建议使用sigaction()来代替signal函数。而实际在linux中,signal()库函数就是用sigaction()实现的。当然,signal()系统调用并不是这样,存在缺陷。在Linux终端man signal,有如下一段:

The situation on Linux is as follows:


       * The kernel's signal() system call provides System V semantics.


       * By default, in glibc 2 and later, the signal() wrapper function  does

         not  invoke  the  kernel system call.  Instead, it calls sigaction(2)

         using flags that supply BSD semantics.  This default behavior is pro‐

         vided  as  long as the _BSD_SOURCE feature test macro is defined.  By

         default, _BSD_SOURCE is defined; it is also implicitly defined if one

         defines _GNU_SOURCE, and can of course be explicitly defined.


         On  glibc  2  and later, if the _BSD_SOURCE feature test macro is not

         defined, then signal() provides System  V  semantics.   (The  default

         implicit  definition  of  _BSD_SOURCE  is not provided if one invokes

         gcc(1) in one of its standard modes (-std=xxx or  -ansi)  or  defines

         various   other   feature   test   macros   such   as  _POSIX_SOURCE,

         _XOPEN_SOURCE, or _SVID_SOURCE; see feature_test_macros(7).)


       * The signal() function in Linux  libc4  and  libc5  provide  System  V

         semantics.   If one on a libc5 system includes <bsd/signal.h> instead

         of <signal.h>, then signal() provides BSD semantics.

而且,现在的Linux版本一般都默认定义了_BSD_SOURCE,因此,一般情况下直接使用signal()不会存在问题。
0 0
原创粉丝点击