你的位置:首页 > 操作系统

[操作系统]信号处理程序(signal handler)会被重置的函数


  首先说明我的系统,CentOS 6.6,内核为2.6.32-504.12.2.el6.i686。

  当用signal对某个信号设定信号处理函数的时候,有些信号的处理函数会被重置,有些则不会,这种情况的具体说明我还没有找到,这里我就先列一下我找到的几个信号。

 

  信号处理程序会被重置的信号:

  1. SIGALRM

    比如下面这段代码,这段代码的作用就是给自己发送SIGALRM信号,直到发送了NUM次。

 1 #include <errno.h> 2 #include <pwd.h> 3 #include <signal.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <stdarg.h> 7 #include <stdio.h> 8 #include <sys/types.h> 9 #include <unistd.h>10 11 #define BUFSIZE 51212 #define NUM 513 14 /*15  * 这三个函数是我自定义的,功能就是利用strerror打印errno的信息,并且退出16 */17 void err_exit(char *fmt,...);18 int err_dump(char *fmt,...);19 int err_ret(char *fmt,...);20 21 int alrm_count = 0;  //对发送的alrm信号进行计数22 /*23  * 本函数用来处理SIGALRM信号24 */25 void sig_alrm(int signo)26 {27   alrm_count++;28   printf("In signal SIGALRM handler\n");29   if(SIG_ERR == signal(SIGALRM,sig_alrm))30     err_exit("[signal]: ");31   if(alrm_count < NUM) {32     alarm(1);33     pause();34   }35 }36 37 int main(int argc,char *argv[])38 {39   if(SIG_ERR == signal(SIGALRM,sig_alrm))40     err_exit("[signal]: ");41 42   /*alarm函数的功能就是在1s之后向本进程发送一个SIGALRM信号*/43   alarm(1);44   pause();45 46   return 0;47 }

  这个程序的29~30行就是在信号的处理函数中重新设置对SIGALRM的处理函数,下次产生SIGALRM这个信号的时候,继续来调用这个处理函数。程序的运行结果如下:

  

  如果没有29~30行那两行的内容,程序的运行结果就会变成下面这样:

  

  第一次接受到SIGALRM信号,程序会调用我们自定义的sig_alrm信号处理函数,但是第二次接受到SIGALRM信号的时候,程序就会调用系统默认的SIGALRM的信号处理函数了,此时就会打印出Alarm clock信息。

 

  2. SIGCHLD信号(SIGCLD)

    在linux下面,这两个信号是等价的,所以就放在一起来讨论。首先先把代码贴上来:

 1 #include <errno.h> 2 #include <signal.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <stdarg.h> 6 #include <stdio.h> 7 #include <sys/types.h> 8 #include <sys/wait.h> 9 #include <unistd.h>10 11 #define BUFSIZE 51212 #define NUM 213 14 void err_exit(char *fmt,...);15 int err_dump(char *fmt,...);16 int err_ret(char *fmt,...);17 18 void sig_chld(int signo);19 20 int main(int argc,char *argv[])21 {22   pid_t pid;23 24   if(SIG_ERR == signal(SIGCHLD,sig_chld))25     perror("[signal]: ");26 27   for(int loop=0;loop<NUM;loop++) {28     if(-1 == (pid=fork())) {29       err_exit("[fork]:");30     } else if(0 == pid) {31       printf("I'm the No.%d Child %d\n",loop+1,getpid());32       return 0;33     } else {34       pause();35     }36   }37 38   return 0;39 }40 41 void sig_chld(int signo)42 {43   int status;44   pid_t cpid;45 46   /* printf("A child process terminated!\n"); */47   if(-1 == (cpid=wait(&status)))48     err_exit("[wait]: ");49   else50     printf("Process %d terminated!\n",cpid);51 52   if(SIG_ERR == signal(SIGCHLD,sig_chld))53     perror("[signal]: ");54 }

  这段代码的作用就是父进程创建一个子进程,然后暂停,等待子进程结束发送SIGCHLD信号过来,在SIGCHLD信号的信号处理函数中,将子进程回收,并且打印出回收的子进程进程id。执行完这些步骤之后,再来继续这个过程,直到循环了NUM次。

  这个程序的运行结果如下所示:

  

  这里可以看到,两个子进程结束时发送的SIGCHLD信号都被接受到了,并且两个子进程都被回收了。

  如果我去掉了在信号处理函数中的signal函数(52~53行),那么程序的运行结果就会如下图所示:

  

  主函数卡死了,此时我用top命令来查看这进程信息,发现第二个子进程变成了僵尸进程,如下图所示:

  

  此时SIGCHLD信号处理函数,变成了默认的忽略(SIG_IGN),接受到了SIGCHLD信号就不会调用函数了,而pause函数的说明则是这样的:

  

  pause函数只有遇到让主进程终止的信号,或者是产生信号处理函数调用的函数才会停止睡眠。而在上面的程序中,第二次的时候SIGCHLD信号由于采用的系统默认的配置SIG_IGN,此时不会产生信号处理函数的调用,所以主进程就继续暂停。

 

  信号处理程序不会被重置的信号:

  目前我只发现了两个,就是两个用户自定义的函数,SIG_USR1和SIG_USR2,具体可以参看下面这段代码:

 1 #include<errno.h> 2 #include<signal.h> 3 #include<string.h> 4 #include<stdlib.h> 5 #include<stdarg.h> 6 #include<stdio.h> 7 #include<unistd.h> 8  9 #define BUFSIZE 51210 11 /*12  * 这三个函数是我自定义的,功能就是利用strerror打印errno的信息,并且退出13 */14 void err_exit(char *fmt,...);15 void err_dump(char *fmt,...);16 int err_ret(char *fmt,...);17 18 void sig_handler(int signo)19 {20   if(signo == SIGUSR1)21     printf("Catch the SIGUSR1 [%d]\n",signo);22   else if(signo == SIGUSR2)23     printf("Catch the SIGUSR2 [%d]\n",signo);24   else25     err_dump("Catch the signal %d\n",signo);26 }27 int main(int argc,char *argv[])28 {29   if(SIG_ERR == signal(SIGUSR1,sig_handler))30     err_exit("[signal]1: ");31   if(SIG_ERR == signal(SIGUSR2,sig_handler))32     err_exit("[signal]2: ");33 34   for(;;)35     pause();36 37   return 0;38 }

  这个程序就是一直等待信号发送过来,并且会对SIGUSR1和SIGUSR2进行处理,其他信号则会执行系统默认的处理情况。运行的结果如下图:

  程序开始后,我通过另一个终端给这个程序发送信号,如下图所示:

  

  而程序运行的界面如下图所示:

  

  从这里可以看出,我们只对SIGUSR这两个函数设置了一次信号处理函数,但是它们的处理方式就不会被重置,发送多次SIGUSR信号都是同一种处理方式。

 




什么时候去重庆旅游最好重庆跟团旅游报价多少重庆旅游必去的地方是重庆旅游必去景点排名重庆旅游地图线路大全岳麓山门票_湖南长沙岳麓山门票_长沙岳麓山要门票吗 伏牛山在哪_伏牛山在哪里_伏牛山在哪个省 木格措海拔_康定情歌风景区木格措海拔高度是多少 世界公园地址_世界公园在哪_世界公园在什么地方 母亲节感恩之旅一起远游为爱而行 十月年 关岛体验爱的气息 河北13处景区入选全国红色经典景区 潍坊富华游乐园通票一天没玩完第二天可以接着玩吗?富华游乐园门票几天有效? 富华游乐园摩天轮多少钱?潍坊富华游乐园摩天轮好玩吗? 潍坊富华游乐园游玩攻略?富华游乐园有摩天轮吗? 2015浮盖山峡谷漂流什么时间开始?江山浮盖山峡谷漂流开漂时间? 2015深圳欢乐谷圣诞节夜场活动时间?深圳欢乐谷圣诞夜场几时开始? 2015世界之窗圣诞节夜场活动时间?深圳世界之窗圣诞夜场几时开始? 2015深圳锦绣中华圣诞节夜场活动时间?锦绣中华圣诞夜场几时开始? 2015深圳圣诞节情侣拍拖去哪好玩?深圳圣诞夜约会哪里好? STW13NB60 Datasheet STW13NB60 Datasheet STW13NK60Z Datasheet STW13NK60Z Datasheet STW18NM60N Datasheet STW18NM60N Datasheet 情人节那天 情人节那天 情人节那天 羊台山好玩吗 羊台山好玩吗 羊台山好玩吗 深圳高铁订票电话 深圳高铁订票电话 深圳高铁订票电话