Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1270643
  • 博文数量: 160
  • 博客积分: 4132
  • 博客等级: 中校
  • 技术积分: 2086
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-06 21:56
文章分类

全部博文(160)

文章存档

2012年(25)

2011年(120)

2010年(15)

分类: LINUX

2011-09-05 08:47:05


sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。

他是POSIX的信号接口,而signal()是标准C的信号接口(如果程序必须在非POSIX系统上运行,

那么就应该使用这个接口)

给信号signum设置新的信号处理函数act, 同时保留该信号原有的信号处理函数oldact

int sigaction(int signo,const struct sigaction *restrict act,

              struct sigaction *restrict oact);

结构sigaction定义如下:

struct sigaction{
  void (*sa_handler)(int);
   sigset_t sa_mask;
  int sa_flag;
  void (*sa_sigaction)(int,siginfo_t *,void *);
};

sa_handler字段包含一个信号捕捉函数的地址

sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信

号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

sa_flag是一个选项,主要理解两个

SA_INTERRUPT 由此信号中断的系统调用不会自动重启
SA_RESTART 由此信号中断的系统调用会自动重启

SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符

的指针

最后一个参数是一个替代的信号处理程序,当设置SA_SIGINFO时才会用他。

例子:

#include
#include
#include

void show_handler(int sig)
{
    printf("I got signal %d\n", sig);
    int i;
    for(i = 0; i < 5; i++) {
        printf("i = %d\n", i);
        sleep(1);
    }
}

int main(void)
{
    int i = 0;
    struct sigaction act, oldact;
    act.sa_handler = show_handler;
    sigaddset(&act.sa_mask, SIGQUIT); //见注(1)
    act.sa_flags = SA_RESETHAND | SA_NODEFER; //见注(2)
    //act.sa_flags = 0; //见注(3)

    sigaction(SIGINT, &act, &oldact);
    while(1) {
        sleep(1);
        printf("sleeping %d\n", i);
        i++;
    }
}


注:
(1)    如果在信号SIGINT(Ctrl + c)的信号处理函数show_handler执行过程中,本进

程收到信号SIGQUIT(Crt+\),将阻塞该信号,直到show_handler执行结束才会处理信号

SIGQUIT。


(2)    SA_NODEFER       一般情况下, 当信号处理函数运行时,内核将阻塞<该给

定信号 -- SIGINT>。但是如果设置了SA_NODEFER标记, 那么在该信号处理函数运行时

,内核将不会阻塞该信号。 SA_NODEFER是这个标记的正式的POSIX名字(还有一个名

字SA_NOMASK,为了软件的可移植性,一般不用这个名字)    
       SA_RESETHAND    当调用信号处理函数时,将信号的处理函数重置为缺省值。 

SA_RESETHAND是这个标记的正式的POSIX名字(还有一个名字SA_ONESHOT,为了软件的

可移植性,一般不用这个名字)   


(3)    如果不需要重置该给定信号的处理函数为缺省值;并且不需要阻塞该给定信

号(无须设置sa_flags标志),那么必须将sa_flags清零,否则运行将会产生段错误。

但是sa_flags清零后可能会造成信号丢失!




linux信号机制之sigaction结构体浅析  

2009-02-20 16:47:00|  分类: linux|字号

        转http://hi.baidu.com/phenix_yw/blog/item/6eb4ca391d1479f23a87ce19.html

     信号安装函数sigaction(int signum,const struct sigaction *act,struct sigaction *oldact)的第二个参数是一个指向sigaction结构的指针(结构体名称与函数名一样,千万别弄混淆了)。在结构sigaction的实例中,指定了对特定信号的处理,信号所传递的信息,信号处理函数执行过程中应屏蔽掉哪些函数等。当然,此指针也可以为NULL,进程会以默认方式处理信号。以下就简单介绍一下sigaction结构以及一般的用法。

        对于内核头文件而言,struct sigaction 结构体定义在kernel/include/asm/signal.h,此头文件又被kernel/include/linux/signal.h包含。
        对于用户空间的头文件而言,struct sigaction定义在 /usr/include/bits/sigaction.h,此头文件又被/usr/include/signal.h包含,所以应用程序中如果用到此结构,只要#include 即可。注意内核中的定义和应用程序中的定义是不一样的,内核空间的sigaction结构只支持函数类型为__sighandler_t的信号处理函数,不能处理信号传递的额外信息。具体定义如下:

……
/* Type of a signal handler.   */
typedef void (*__sighandler_t)(int);

……
#ifdef __KERNEL__
struct old_sigaction {
          __sighandler_t sa_handler;
         old_sigset_t sa_mask;
         unsigned long sa_flags;
         void (*sa_restorer)(void);
};

struct sigaction {
         __sighandler_t sa_handler;
        unsigned long sa_flags;
        void (*sa_restorer)(void);
        sigset_t sa_mask;   /* mask last for extensibility */
};

struct k_sigaction {
        struct sigaction sa;
};

#else
/* Here we must cater to libcs that poke about in kernel headers.   */

struct sigaction {
          union {
                  __sighandler_t _sa_handler;
                  void (*_sa_sigaction)(int, struct siginfo *, void *);
          } _u;
          sigset_t sa_mask;
          unsigned long sa_flags;
          void (*sa_restorer)(void);
};

#define sa_handler   _u._sa_handler
#define sa_sigaction _u._sa_sigaction

#endif /* __KERNEL__ */

sa_handler的原型是一个参数为int,返回类型为void的函数指针。参数即为信号值,所以信号不能传递除信号值之外的任何信息;

sa_sigaction的原型是一个带三个参数,类型分别为int,struct siginfo *,void *,返回类型为void的函数指针。第一个参数为信号值;第二个参数是一个指向struct siginfo结构的指针,此结构中包含信号携带的数据值;第三个参数没有使用。

sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。默认当前信号本身被阻塞。

sa_flags包含了许多标志位,比较重要的一个是SA_SIGINFO,当设定了该标志位时,表示信号附带的参数可以传递到信号处理函数中。即使sa_sigaction指定信号处理函数,如果不设置SA_SIGINFO,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误。

sa_restorer已过时,POSIX不支持它,不应再使用。

        因此,当你的信号需要接收附加信息的时候,你必须给sa_sigaction赋信号处理函数指针,同时还要给sa_flags赋SA_SIGINFO,类似下面的代码:
     #include
     ……
     void sig_handler_with_arg(int sig,siginfo_t *sig_info,void *unused){……}
    
     int main(int argc,char **argv)
     {
              struct sigaction sig_act;
              ……
              sigemptyset(&sig_act.sa_mask);
              sig_act.sa_sigaction=sig_handler_with_arg;
              sig_act.sa_flags=SA_SIGINFO;
  
               ……
     }
        如果你的应用程序只需要接收信号,而不需要接收额外信息,那你需要的设置的是sa_handler,而不是sa_sigaction,你的程序可能类似下面的代码:
     #include
     ……
     void sig_handler(int sig){……}
    
     int main(int argc,char **argv)
     {
              struct sigaction sig_act;
              ……
              sigemptyset(&sig_act.sa_mask);
              sig_act.sa_handler=sig_handler;
              sig_act.sa_flags=0;
  
               ……
      }

阅读(1704) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~