信号处理程序(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 512
12 #define NUM 5
13
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 512
12 #define NUM 2
13
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     else
50         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 512
10
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     else
25       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信号都是同一种处理方式。

时间: 2024-08-04 14:05:05

信号处理程序(signal handler)会被重置的信号的相关文章

Linux信号(signal) 机制分析

[摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核对于信号的处理流程包括信号的触发/注册/执行及注销等.最后介绍了应用层的相关处理,主要包括信号处理函数的安装.信号的发送.屏蔽阻塞等,最后给了几个简单的应用实例. [关键字]软中断信号,signal,sigaction,kill,sigqueue,settimer,sigmask,sigprocmask,sigset_t 1       信

信号(二)---signal函数详解

前面提到了当进程收到了信号后,有三种处理信号的方法:忽略该信号:执行默认动作:捕捉该信号. 捕捉信号 的意思就是当进程收到一个信号时去执行我们指定的动作.signal 函数就是Linux系统提供用来捕捉信号的函数. ======================================================== 函数原型: 函数参数: signum:捕捉的信号 handler:收到信号后执行的动作,是个函数指针变量 返回值: 调用失败时返回 SIG_ERR 调用成功时返回 指向之

[学习笔记]信号基本概念(中断和信号)/名称及常用信号/信号处理/signal函数实践

1基本概念 中断 q  中断是系统对于异步事件的响应 q  中断信号 q  中断源 q  现场信息 q  中断处理程序 q  中断向量表 异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序 生活中的中断和计算机系统中的中断 1)  无中断生活场景 张三看书,厨房烧水 2)有中断的生活场景 张三看书,设置闹钟,厨房烧水. 闹钟发出中断信号,张三把书合好(第20页),去厨房把开水事情处理好,张三重新打开20页进行阅读. 3)计算机系统的中断场景 中断源发出中断信号,CPU判断

捕捉段错误信号信号处理程序

//简单的捕捉段错误信号信号处理程序,通过signal来捕捉错误. #include<stdio.h>#include<signal.h>#include<stdlib.h>void handler(int s){    if(s == SIGINT) printf("now got a interrupt signal  ");    if(s == SIGSEGV) printf("now got a segmentation viol

信号之signal函数的使用

typedef  void(*sighandler_t)(int)    =====>  xxx   就是  void xxx(int y)  的函数指针 入口地址  sighandler_t signal(int signum,sighandler_t handler)  =====>void (*signal(int signum , (void *))(int)))(int) handler就是函数的入口地址 /* #include<signal.h> 作用:注册信号的行为

23:django 信号(signal)

django包含了一个“信号分配器”使得当一些动作在框架的其他地方发生的时候,解耦的应用可以得到提醒.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者,这是特别有用的设计因为有些代码对某些事件是特别感兴趣的,比如删除动作. 为此,django提供了很多内置的信号,比如一些常用的功能(以几个在django.db.models.signal目录下的信号为例): save:pre_save和post_save delete:pre_delete和post_delete chang

APUE 3 -- 信号 (signal)&lt;II&gt;: 可靠信号

一个事件可以使一个信号发送给一个进程,这个事件可以是硬件异常,可以是软件条件触发,可以是终端产生信号,也可以是一个kill函数调用.当信号产生后,内核通常会在进程表中设置某种形式的标志(flag).我们可以认为当进程中的信号处理函数被触发的时候认为信号下达到了(delivered)这个进程.从信号产生到信号下达到进程这段期间,信号被认为是挂起状态(pending).进程拥有阻塞信号下达的选项.如果一个阻塞信号要发送给一个进程,而且信号的处理方式是默认处理或者被进程捕获,那么这个信号将一直处于挂起

Linux 信号:signal 与 sigaction

0.Linux下查看支持的信号列表: [email protected]:~$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCON

Linux下利用signal函数处理ctrl+c等信号

前言 linux下可以通过信号机制来实现程序的软中断,是一个非常有用的编程方法.我们平时在程序运行的时候按下ctrl-c.ctrl-z或者kill一个进程的时候其实都等效于向这个进程发送了一个特定信号,当进程捕获到信号后,进程会被中断并立即跳转到信号处理函数.默认情况下一个程序对ctrl-c发出的信号(SIGINT)的处理方式是退出进程,所以当我们按下ctrl-c的时候就可以终止一个进程的运行. signal函数 但是有时候我们希望我们的程序在被信号终止之前执行一些特定的收尾流程,或者我们希望我