信号2笔记

来源:互联网 发布:淘宝怎样删除评价记录 编辑:程序博客网 时间:2024/05/20 22:37
 系统有以下处理信号的组合:1、不可靠的信号(捕鼠器)如果先后出现两个SIGINT信号杀死了进程,那么意味着你的系统是不可靠的信号:处理函数必须每次都重置。sa_flags的值为SA_RESETHAND,就是这种信号:在调用信号处理函数时,将信号的处理方式重置为SIG_DEL。所以出现第二SIGINT信号,按默认方式终止了进程。什么是捕鼠器:           一个信号意味着什么具有破坏性的事情发生,并被捕获。当信号或老鼠被捕获后,信号处理函数或捕鼠器就失效了。在早期的版本中,信号处理函数在另一个方面也像捕鼠器:在每次捕获之后,都必须重新设置它们。但设置也需要时间,在弹簧被触发和设置完成之间,就有可能有老鼠溜走了。这一脆弱的间隙使得原有信号处理不可靠,有些人称此为“不可靠的信号”。例:#include <stdio.h>#include <signal.h>#define INPUTLEN 100int main(void){        void inhandler(int);        char input[INPUTLEN];        int nchars;        struct sigaction newhandler;        sigset_t blocked;        newhandler.sa_handler=inhandler;        sigemptyset(&blocked);        newhandler.sa_mask=blocked;        newhandler.sa_flags=SA_RESETHAND;        sigaction(SIGINT,&newhandler,NULL);        do{                printf("\nType a message\n");                nchars=read(0,input,(INPUTLEN-1));                if(nchars==-1)                        perror("read returned an error");                else {                        input[nchars]='\0';                        printf("You typed:%s",input);                }        }while(strncmp(input,"quit",4)!=0);}void inhandler(int s){        printf("Received signal %d .. waiting\n",s);        sleep(2);        printf("Leaving inthandler\n");}运行结果:[root@localhost ~]# ./a.out^c^cType a messageReceived signal 2 .. waitingLeaving inthandler[root@localhost ~]#退出了进程2、SIGY打断SIGX的信号处理函数。就像是在工作时接到了一个电话,处理这个电话意味着放下当前的工作,拿起电话,与打电话的人交谈,挂起电话,然后回去做放在一边的工作。像下面的程序:当接连按下ctrl-c和ctrl-\会看到程序先跳到inthandler,接着跳到quithandler,然后再回到inthandler,最后回到主循环。#include <stdio.h>#include <signal.h>#define INPUTLEN 100int main(void){ void inthandler(int); void quithandler(int); char input[INPUTLEN]; int nchars; signal(SIGINT,inthandler); signal(SIGQUIT,quithandler);  do{  printf("\nType a message\n");  nchars=read(0,input,(INPUTLEN-1));  if(nchars==-1)   perror("read returned an error");  else {   input[nchars]='\0';   printf("You typed:%s",input);  } }while(strncmp(input,"quit",4)!=0);}void inthandler(int s){ printf("Received signal %d .. waiting\n",s); sleep(2); printf("Leaving inthandler\n");}void quithandler(int s){ printf("Received signal %d .. waiting\n",s); sleep(2); printf("Leaving quithandler\n");}运行结果:[root@localhost ~]# ./a.out^c^\Type a messageReceived signal 2 .. waitingReceived signal 3 .. waitingLeaving quithandlerLeaving inthandler光标在此,等待输入。[root@localhost ~]# ./a.out^cType a messageReceived signal 2 .. waiting^c Leaving inthandler          在调用信号处理函数inthandler内的2秒休眠时再发出一个SIGINT信号Received signal 2 .. waitingLeaving inthandler结论:当调用一个信号处理程序时,被捕捉到的信号添加到进程的当前信号屏蔽字中,当从信号处理程序返回时,恢复原来的屏蔽字,所以第二个SIGINT信号等到第一次信号处理程序返回主程序后再调用一次信号处理程序。3、SIGX打断SIGX的信号处理函数这种情况就像两个人来敲门,有3种处理的方法:1)递归,调用同一个处理函数sa_flags的值为SA_NODEFER是采用递归:当捕捉到多个此信号,某个此信号都会调用同一个信号处理程序,系统不自动阻塞此信号。例:#include <stdio.h>#include <signal.h>#define INPUTLEN 100int main(void){        void inhandler(int);        char input[INPUTLEN];        int nchars;        struct sigaction newhandler;        sigset_t blocked;        newhandler.sa_handler=inhandler;        sigemptyset(&blocked);        newhandler.sa_mask=blocked;        newhandler.sa_flags=SA_NODEFER;        sigaction(SIGINT,&newhandler,NULL);        do{                printf("\nType a message\n");                nchars=read(0,input,(INPUTLEN-1));                if(nchars==-1)                        perror("read returned an error");                else {                        input[nchars]='\0';                        printf("You typed:%s",input);                }        }while(strncmp(input,"quit",4)!=0);}void inhandler(int s){        printf("Received signal %d .. waiting\n",s);        sleep(2);        printf("Leaving inthandler\n");}运行结果:[root@localhost ~]# ./a.out^c^c^cType a messageReceived signal 2 .. waitingReceived signal 2 .. waitingReceived signal 2 .. waitingLeaving inthandlerLeaving inthandlerLeaving inthandlerread returned an error: Interrupted system callType a message等待输入并发现被中断的系统调用错误返回了,并不重新开始。2)忽略第二个信号3)阻塞第二个信号直到第一个处理完毕sa_mask字段说明了一个信号集,在调用信号捕捉函数之前,这一信号集要加到进程的信号屏蔽中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。因此保证了在处理一个给定的信号时,如果这种信号再次发生,那么它会阻塞到对前一个信号的处理结束为止。例1:#include <stdio.h>#include <signal.h>#define INPUTLEN 100int main(void){        void inhandler(int);        char input[INPUTLEN];        int nchars;        struct sigaction newhandler;        sigset_t blocked;        newhandler.sa_handler=inhandler;        sigemptyset(&blocked);        sigaddset(&blocked,SIGINT);        newhandler.sa_mask=blocked;        sigaction(SIGINT,&newhandler,NULL);        do{                printf("\nType a message\n");                nchars=read(0,input,(INPUTLEN-1));                if(nchars==-1)                        perror("read returned an error");                else {                        input[nchars]='\0';                        printf("You typed:%s",input);                }        }while(strncmp(input,"quit",4)!=0);}void inhandler(int s){        printf("Received signal %d .. waiting\n",s);        sleep(2);        printf("Leaving inthandler\n");}运行结果:[root@localhost ~]# ./a.out^c^cType a messageReceived signal 2 .. waitingLeaving inthandlerReceived signal 2 .. waitingLeaving inthandlerread returned an error: Interrupted system callType a message等待输入第一个ctrl-c,调用了信号处理函数,在调用前阻塞了SIGINT信号,此时再按下ctrl-c时,第二个信号被阻塞,在第一个处理函数完毕,消除了对SIGINT的阻塞,然后再调用第二个信号处理函数例2:#include <stdio.h>#include <signal.h>#define INPUTLEN 100int main(void){        void inhandler(int);        char input[INPUTLEN];        int nchars;        struct sigaction newhandler;        sigset_t blocked;        newhandler.sa_handler=inhandler;        sigemptyset(&blocked);        sigaddset(&blocked,SIGQUIT);        newhandler.sa_mask=blocked;        sigaction(SIGINT,&newhandler,NULL);        do{                printf("\nType a message\n");                nchars=read(0,input,(INPUTLEN-1));                if(nchars==-1)                        perror("read returned an error");                else {                        input[nchars]='\0';                        printf("You typed:%s",input);                }        }while(strncmp(input,"quit",4)!=0);}void inhandler(int s){        printf("Received signal %d .. waiting\n",s);        sleep(2);        printf("Leaving inthandler\n");}运行结果:[root@localhost ~]# ./a.out^c^\Type a messageReceived signal 2 .. waitingLeaving inthandler退出如果以很快的速度连续按ctrl-c和ctrl-\,退出信号将被阻塞直到中断信号处理完毕,完毕后,退出信号按默认动作终止进程。4、被中断的系统调用就像打电话时有人敲门,去开门,开好门后,拉起电话,将此电话已断了还是重新开始交谈。程序经常在等待输入的时候收到信号,从信号处理函数返回后,是系统调用函数重新开始输入,还是系统调用函数直接返回错误了?sa_flags的值SA_RESTART:是系统调用重新开始而不是返回-1。例:#include <stdio.h>#include <signal.h>#define INPUTLEN 100int main(void){        void inhandler(int);        char input[INPUTLEN];        int nchars;        struct sigaction newhandler;        sigset_t blocked;        newhandler.sa_handler=inhandler;        sigemptyset(&blocked);        newhandler.sa_mask=blocked;        newhandler.sa_flags=SA_RESTART;        sigaction(SIGINT,&newhandler,NULL);        do{                printf("\nType a message\n");                nchars=read(0,input,(INPUTLEN-1));                if(nchars==-1)                        perror("read returned an error");                else {                        input[nchars]='\0';                        printf("You typed:%s",input);                }        }while(strncmp(input,"quit",4)!=0);}void inhandler(int s){        printf("Received signal %d .. waiting\n",s);        sleep(2);        printf("Leaving inthandler\n");}运行结果:[root@localhost ~]# ./a.outType a messagehel^cReceived signal 2 .. waitingloLeaving inthandlerYou typed:loType a message光标等待输入这是输入"hel",接着按下ctrl-c然后再继续输入"lo"再回车的结果。sa_flags的值SA_INTERRUPT:系统调用不重新开始而是返回-1,同时设置errno到EINTR。例:#include <stdio.h>#include <signal.h>#define INPUTLEN 100int main(void){        void inhandler(int);        char input[INPUTLEN];        int nchars;        struct sigaction newhandler;        sigset_t blocked;        newhandler.sa_handler=inhandler;        sigemptyset(&blocked);        newhandler.sa_mask=blocked;        newhandler.sa_flags=SA_INTERRUPT;        sigaction(SIGINT,&newhandler,NULL);        do{                printf("\nType a message\n");                nchars=read(0,input,(INPUTLEN-1));                if(nchars==-1)                        perror("read returned an error");                else {                        input[nchars]='\0';                        printf("You typed:%s",input);                }        }while(strncmp(input,"quit",4)!=0);}void inhandler(int s){        printf("Received signal %d .. waiting\n",s);        sleep(2);        printf("Leaving inthandler\n");}运行结果:[root@localhost ~]# ./a.outType a messagehelReceived signal 2 .. waitingLeaving inthandlerread returned an error: Interrupted system callType a message等待输入这是输入"hel",接着按下ctrl-c,系统调用函数read返回-1,不重新开始