/**
* @file demo7.c
* @Synopsis
*
* int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact)
* @param signum
* @param struct sigaction * oldact -> NULL
* @param const struct sigaction *act
*
* 注:阻塞的意思是延迟相应信号
* sigaction,是为替代signal 来设计的较稳定的信号处理。
* typedef void (*sighandler_t)(int);
* sighandler_t signal(int signum,sighandler_t handler);
* 不能完成的任务:{
* 1:不知道信号产生的原因;
* 2:处理信号中不能阻塞其他信号
* }
* 而signaction , 则可以设置比较多的信号消息。
* 尤其是在信号处理函数过程中接受信号,进行何种处理。
*
* sigaction 函数用于改变进程接收到特定信号后的行为。
* 该函数的第一个参数为信号的值,可以为除SIGKILL 及SIGSTOP外的任何一个特定有效的信号(为
* 这两个信号定义自己的处理函数,将导致信号安装错误)。
* 第二个参数是指向结构sigaction 的一个实例的指针,在结构体sigaction的实例中,指定了对
* 特定信号的处理,可以为空,进程会以缺省方式对信号处理;
* 第三个参数oldact 指向的对象用来保存原来对应信号的处理,可指定oldact 为NULL.
* 如果把第二,第三个参数都设为NULL,那么该函数可用于检查信号的有效性。
* 第二个参数最为重要,其中包含了对指定信号的处理,信号所传递的信息,信号处理函数执行过程
* 中应屏蔽掉哪些函数等等。
*
* struct sigaction{
* void (*sa_handler)(int);// like signal
* void (*sa_sigaction)(int,siginfo_t *,void *);//
* sigset_t sa_mask;
* int sa_flags;
* void (*sa_restorer)(void);
* }
* 其中sa_restorer,己过时POSIX不支持它,不再使用它
*
* SIGKILL and SIGSTOP 这两个信号是不能屏蔽的。
* 如果 sa_flags -> SA_SIGINFO....则会调用 sigaction
* sa_mask 指出来一组信号,可以被阻塞。。
*
* sa_flags{
* SA_NODEFER
* SA_RESETHAND
* SA_RESTART
* SA_SIGINFO
* }
* sa_mask{
*
* // 信号设置,信号集合,一堆信号。kill -l
* // 小于 34的 叫普通信号
* // 大于等于34 叫实施信号
* // sigset_t 看成一个整数
* sigset_t{
* sigismember // 判断某一个信号是否在里面
* setfillset/sigdelset // 把所有位置位1,/把里面的某一个位删除设置0
* sigemptyset/sigaddset // 集合里面所有位清0 /把某一个清0
* }
* sigprocmask
* }
*
* sigset_t s1;
* 0 0 0 0 0 0 0 0 0
* 集合:0 1 2 3 4 5 6 7 8
*
* s1 = 2;
* 怎么样得到一个信号集合。。
* 我们有一糸列的函数
* 信号集合大于16
* fill 往后面减。
* 小于16个信号
* 清空往里面加
* 不同糸统作法不一样。。
*
* signal 间接调用 sigaction
* @author MrClimb
* @version 1.1.0
* @date 2012-05-20
*/
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#define INPUTLEN 100
void inthandler();
int main(int argc, char **argv)
{
struct sigaction newhandler;
sigset_t blocked;// 信号集合
char x[INPUTLEN];
newhandler.sa_handler = inthandler;
// 不加SA_NODEFER 只处理一次性号。
// 而加上则每次信号都将处理。
// newhandler.sa_flags = SA_RESTART;// ^C 只接收一次性号。连续按不接收; 设置 0 也可以;
// 3)当上面去掉了SA_NODEFER标志位。程序在执行信号处理函数过程中,^C信号将会被阻止,
// 但是执行信号处理函数期发送的^C信号将会被阻塞,知道信号处理函数执行完成,才有机会处理
// 信号函数执行期间产生的^C,但是在信号函数执行产生的多次^C,最后只产生^C
// 而下面设置了SA_NODEFER,^C信号将不会被阻塞。所以能够并行执行下次的信号处理函数。
// newhandler.sa_flags = SA_RESTART | SA_NODEFER;// ^C 连续按每一次都接收(程序都不会结束)
// 1)第一次产生^C 信号时候,该信号被自己设定的信号处理函数时行了处理。在处理过程中,
// 由于这里设定了SA_RESETHAND标志位,又将该信号的处理函数设置为默认的信号处理
// 函数(糸统默认的处理方式为IGN),所以在第二次发送^C信号的时候,是由默认的信号
// 算是函数处理的,导致程序结束,
// 2) 当根据上面没有SA_RESETHAND标志位,导致程序中所有的^C信号均是由我们自己的信号
// 处理函数来进行处理,所以我们发关多少次^C信号程序都不会退出
newhandler.sa_flags = SA_RESTART | SA_NODEFER | SA_RESETHAND;// ^C 按一次执行,按第二次^C 则停止该进程
sigemptyset(&blocked);
sigaddset(&blocked,SIGQUIT);// 往集合里加一个SIGQUIT 信号(^\)
sigaddset(&blocked,SIGTSTP);// 添加 终止信号 ^Z
/**
* sa_mask 在信号处理函数运行时 屏蔽所有的信号除了SIGSTOP & SIGKILL 两个信号外,
* 当然上面blocked 信号被置空了,重新设置了上面两个信号,当接收到上面两个信号,则
* 执行屏蔽操作,退出程序。
*/
newhandler.sa_mask = blocked;// 将blocked 传给 sa_mask 时,它才屏蔽后一个信号
if(sigaction(SIGINT,&newhandler,NULL)== -1)
{
perror("sigaction");
}else
{
while(1)
{
fgets(x,INPUTLEN,stdin);
printf("input: %s",x);
}
}
return 0;
}
void inthandler(int s)
{
printf("Called with signal %d\n",s);
sleep(s*3);
printf("done handling signal %d\n",s);
}
原文:http://mrjake.blog.163.com/blog/static/10510910620124223322168/