newlist

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

#include <signal.h>

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

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

通过sa_mask设置信号掩码集。

信号处理函数可以采用void (*sa_handler)(int)或void (*sa_sigaction)(int, siginfo_t *, void *)。到底采用哪个要看sa_flags中是否设置了SA_SIGINFO位,如果设置了就采用void (*sa_sigaction)(int, siginfo_t *, void *),此时可以向处理函数发送附加信息;默认情况下采用void (*sa_handler)(int),此时只能向处理函数发送信号的数值。

sa_falgs还可以设置其他标志:

SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL

SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用

SA_NODEFER :一般情况下, 当信号处理函数运行时,内核将阻塞该给定信号。但是如果设置了SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号

#include<stdio.h> #include<signal.h> #include<stdlib.h> #include<string.h> #define INPUTLEN 100 void inthandler(int); int main(){     struct sigaction newhandler;     sigset_t blocked;       //被阻塞的信号集    char x[INPUTLEN];     newhandler.sa_flags=SA_RESETHAND;     newhandler.sa_handler=inthandler;     sigemptyset(&blocked);      //清空信号处理掩码    sigaddset(&blocked,SIGQUIT);     newhandler.sa_mask=blocked;     if(sigaction(SIGINT,&newhandler,NULL)==-1)         perror("sigaction");     else         while(1){             fgets(x,INPUTLEN,stdin);        //fgets()会在数据的最后附加"\0"            printf("input:%s",x);         } } void inthandler(int signum){     printf("Called with signal %d\n",signum);     sleep(signum);     printf("done handling signal %d\n",signum); }

Ctrl-C向进程发送SIGINT信号,Ctrl-\向进程发送SIGQUIT信号。

$ ./sigactdemo ^CCalled with signal 2 ^\done handling signal 2 Quit (core dumped)

由于把SIGQUIT加入了信号掩码集,所以处理信号SIGINT时把SIGQUIT屏蔽了。当处理完SIGINT后,内核才向进程发送SIGQUIT信号。

$ ./sigactdemo ^CCalled with signal 2 ^Cdone handling signal 2

由于设置了SA_RESETHAND,第一次执行SIGINT的处理函数时相当于执行了signal(SIGINT,SIG_DFL),所以进程第二次收到SIGINT信号后就执行默认操作,即挂起进程。

修改代码,同时设置SA_RESETHAND和SA_NODEFER。

newhandler.sa_flags=SA_RESETHAND|SA_NODEFER;

$ ./sigactdemo ^CCalled with signal 2 ^C

在没有设置SA_NODEFER时,在处理SIGINT信号时,自动屏幕SIGINT信号。现在设置了SA_NODEFER,则当SIGINT第二次到来时立即响应,即挂起了进程。

http://www.cnblogs.com/zhangchaoyang/articles/2297536.html

posted on 2012-02-09 09:40  一枚程序  阅读(671)  评论(0)    收藏  举报