struct sigaction 和信号处理函数的一些说明--1

转自:http://hi.baidu.com/phps/blog/item/b064b7b71944cff630add1b4.html

 

linux 中信号相关的一个结构体 struct sigaction 主要在sigaction信号安装和sigqueue信号发送时会用到
该结构位于/usr/include/bits/sigaction.h
在里面可以找到该结构的描述 {我现在实现的系统是as 4 内核版本 2.6.9-5.EL}
/* Structure describing the action to be taken when a signal arrives.     */
struct sigaction
     {
       /* Signal handler.     */
#ifdef __USE_POSIX199309
       union   
         {
       /* Used if SA_SIGINFO is not set.     */
       __sighandler_t sa_handler;
       /* Used if SA_SIGINFO is set.     */
       void (*sa_sigaction) (int, siginfo_t *, void *);
         }
       __sigaction_handler;


       # define sa_handler __sigaction_handler.sa_handler
       # define sa_sigaction      __sigaction_handler.sa_sigaction
#else
       __sighandler_t sa_handler;
#endif

 

       /* Additional set of signals to be blocked.     */
       __sigset_t sa_mask;

       /* Special flags.     */
       int sa_flags;

       /* Restore handler.     */
       void (*sa_restorer ) (void);
     };

在网上查了一些书料这个结构大概是这样的
其中,sa_restorer,已过时,POSIX不支持它,不应再被使用。
1、联合数据结构中的两个元素_sa_handler以及*_sa_sigaction指定信号关联函数,即用户指定的信号处理函数。除了可以是用户自定义的处理函数 外,还可以为SIG_DFL (采用缺省的处理方式),也可以为SIG_IGN (忽略信号)。
2、由_sa_handler指定的处理函数只有一个参数,即信号值,所以信号不能传递除信号值之外的任何信息

3、由_sa_sigaction是指定的信号处理函数带有三个参数,是为实时信号而设的(当然同样支持非实时信号),它指定一个3参数信号处理函数。第一个参数为信号值,第三个参数没有使用(posix没有规范使用该参数的标准),第二个参数是指向siginfo_t结构的指针,结构中包含信号携带的数据值,参数所指向的结构如下:
在/usr/include/bits/siginfo.h中是这样定义的

typedef struct siginfo
{
     int si_signo;            /* Signal number.     */
     int si_errno;            /* If non-zero, an errno value associated with
                      this signal, as defined in <errno.h>.     */
     int si_code;             /* Signal code.     */

     union
     {
       int _pad[__SI_PAD_SIZE];

       /* kill().     */
       struct
       {
         __pid_t si_pid;          /* Sending process ID.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
       } _kill;

       /* POSIX.1b timers.     */
       struct
       {
         int si_tid;          /* Timer ID.     */
         int si_overrun;          /* Overrun count.     */
         sigval_t si_sigval;      /* Signal value.     */
       } _timer;

       /* POSIX.1b signals.     */
       struct
       {
         __pid_t si_pid;          /* Sending process ID.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
         sigval_t si_sigval;      /* Signal value.     */
       } _rt;

       /* SIGCHLD.     */
       struct
       {
         __pid_t si_pid;          /* Which child.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
         int si_status;           /* Exit value or signal.     */
         __clock_t si_utime;
         __clock_t si_stime;
       } _sigchld;

       /* SIGILL, SIGFPE, SIGSEGV, SIGBUS.     */
       struct
       {
         void *si_addr;           /* Faulting insn/memory ref.     */
       } _sigfault;

       /* SIGPOLL.     */
       struct
       {
         long int si_band;        /* Band event for SIGPOLL.     */
         int si_fd;
       } _sigpoll;
     } _sifields;
} siginfo_t;


是不是太复杂了,在网上有一个简洁版我搬过来用一下

siginfo_t {
                     int         si_signo;     /* 信号值,对所有信号有意义*/
                     int         si_errno;     /* errno值,对所有信号有意义*/
                     int         si_code;      /* 信号产生的原因,对所有信号有意义*/
union{      /* 联合数据结构,不同成员适应不同信号 */
//确保分配足够大的存储空间
int _pad[SI_PAD_SIZE];
//对SIGKILL有意义的结构
struct{
...
     }...
... ...
... ...
//对SIGILL, SIGFPE, SIGSEGV, SIGBUS有意义的结构
         struct{
...
     }...
... ...
     }
}


4、sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。缺省情况下当前信号本身被阻塞,防止信号的嵌套发送,除非指定SA_NODEFER或者SA_NOMASK标志位。

注:请注意sa_mask指定的信号阻塞的前提条件,是在由sigaction()安装信号的处理函数执行过程中由sa_mask指定的信号才被阻塞。

5、sa_flags中包含了许多标志位,包括刚刚提到的SA_NODEFER及SA_NOMASK标志位。另一个比较重要的标志位是SA_SIGINFO,当设定了该标志位时,表示信号附带的参数可以被传递到信号处理函数中,因此,应该为sigaction结构中的sa_sigaction指定处理函数,而不应该为sa_handler指定信号处理函数,否则,设置该标志变得毫无意义。即使为sa_sigaction指定了信号处理函数,如果不设置SA_SIGINFO,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误(Segmentation fault)。

注:很多文献在阐述该标志位时都认为,如果设置了该标志位,就必须定义三参数信号处理函数。实际不是这样的,验证方法很简单:自己实现一个单一参数信号处理函数,并在程序中设置该标志位,可以察看程序的运行结果。实际上,可以把该标志位看成信号是否传递参数的开关,如果设置该位,则传递参数;否则,不传递参数。


结构说的也差不多了,其实在我看到这些东西的时候给弄晕了好几回,简单的说几句就是
如果要在某信号产生时触发某些动作我们就可以安装信号

signal 用于安装不可靠信号     linux现在是用sigaction实现的
sigaction 用于安装可靠信号 当然他也可以安装不可靠信号 并且可以附带更多的信息

signal安装信号时只需传入2个参数 一个是信号的值     一个是信号发生时触发的函数,该函数接受一个整数
sigaction 安装时有3个参数 第一个参数是信号的值,第二个是sigaction结构指针 这个结构说明了信号发生时调用的函数和其它的一些信息。第三个参数也是一个sigaction结构的指针oact,没明白man page的说法,貌似和实际的运行有不符的地方。

If the argument oact is not a null pointer, the action previously associated  with the  signal is stored in the location pointed to by the argument oact. If the argument act is a null pointer, signal handling is unchanged; thus, the call can be used to enquire about the current  handling  of  a  given signal.

 

再说一下sigaction函数的第二个参数,其主要的成员是 sa_handler 指定的触发函数只带一个参数即信号的值 这和signal调用没什么区别,sa_sigaction指定的触发函数带有3个参数 第一个参数是信号的值,第二个参数是包函附加信息的结构siginfo,第三个参数为空 如果要传递附加信息给触发函数那么必须将传给sigaction的第二个参数sigaction结构的sa_flag设为SA_SIGINFO。

加一句,按照我对man的理解,其意思是当sa_flag设置了SA_SIGINFO的时候,就用sa_sigaction,没设置的时候就用sa_handler。

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值