/** * @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); }