信号

传送给进程的事件通知,完成异步通信

 

信号的产生

1.程序错误:硬件异常,除数为0,等

2.外部事件:定时器事件,按键中断(ctrl+c)等

3.显示请求:调用 kill,  raise 等信号发送函数

 

信号的处理

#include<signal.h>

void (*signal (int sig, void(*func)(int))) (int)

      定义一个返回值是函数指针的函数

      signal 函数:

           a) 参数1为整数,参数2为函数指针

           b)返回值类型为:函数指针 void (foo*)(int)

                   值为:上一个处理该信号的函数     

 

解析:

void(*signal(int sig, void(*func)(int)))(int)

 

signal(int sig, void(*func)(int))  -->   这是函数主体

                                   --> 第一个入参是 int

                         --> 第二个入参是 void(*func)(int)

                            -->            这里表示入参是函数指针,

                         -->              类型是 void(*)(int)

 

外部  void(* XXX ) (int)           --> 表示函数的返回值

                         -->        这个返回值是个函数指针

                         -->           类型是 void(*)(int)

 

所以,如果我们 把函数指针定义一下 : typedef void(*FUN)(int)

 

那么,上面的函数可以写成     FUN  signal(int sig, FUN func)

 

信号的处理

系统默认处理

signal(XXX, SIG_DFL)               default

忽略信号

signal(XXX, SIG_IGN)                ignore

捕获信号

signal(XXX, func)

收到XXX 信号,则调用 func 函数

 

使用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) SIGCONT    19) SIGSTOP     20) SIGTSTP

21) SIGTTIN     22) SIGTTOU    23) SIGURG 24) SIGXCPU     25) SIGXFSZ

26) SIGVTALRM 27) SIGPROF     28) SIGWINCH  29) SIGIO   30) SIGPWR

31) SIGSYS  34) SIGRTMIN   35) SIGRTMIN+1     36) SIGRTMIN+2     37) SIGRTMIN+3

38) SIGRTMIN+4     39) SIGRTMIN+5     40) SIGRTMIN+6     41) SIGRTMIN+7     42) SIGRTMIN+8

43) SIGRTMIN+9     44) SIGRTMIN+10   45) SIGRTMIN+11   46) SIGRTMIN+12   47) SIGRTMIN+13

48) SIGRTMIN+14   49) SIGRTMIN+15   50) SIGRTMAX-14    51) SIGRTMAX-13    52) SIGRTMAX-12

53) SIGRTMAX-11    54) SIGRTMAX-10    55) SIGRTMAX-9      56) SIGRTMAX-8      57) SIGRTMAX-7

58) SIGRTMAX-6      59) SIGRTMAX-5      60) SIGRTMAX-4      61) SIGRTMAX-3      62) SIGRTMAX-2

63) SIGRTMAX-1      64) SIGRTMAX  

 

 

例子:

void testSignal()

{

      printf("pid:%d\n",(int)getpid());

      printf("test signal!\n");

 

      while(1);

}

 

在testSignal中死循环,可以使用ctrl+c,中断。

 

下面就对该信号进行处理:

void fun(int sig)

{

      printf("receive signal:%s[%d]\n",strsignal(sig),sig);

}

 

void testSignal()

{

      printf("pid:%d\n",(int)getpid());

      printf("test signal!\n");

      //ctrl+c信号处理

      signal(SIGINT,fun);

 

      while(1);

}

每一次按下ctrl+c,就会触发信号SIGINT,立即调用fun函数。使用kill 进程号。。可终止。

 

下面对kill信号进行处理或者忽略。

void fun(int sig)

{

      printf("receive signal:%s[%d]\n",strsignal(sig),sig);

}

 

void testSignal()

{

      printf("pid:%d\n",(int)getpid());

      printf("test signal!\n");

 

      signal(SIGINT,fun);

      //kill命令的处理

      signal(SIGINT,fun);

      //kill命令的忽略

      //signal(SIGTERM,SIG_IGN);

      while(1);

}

 

sig就是信号的序号,strsignal(sig)就是信号的操作指令。

此时ctrl+c,kill 进程号,都无法终止进程。必须要使用 kill -9 进程号来结束进程。

注意:-9 是信号SIGKILL,此信号无法忽略和处理。

 

 

 

信号的忽略和恢复

void fun(int sig)

{

      printf("receive signal:%s[%d]\n",strsignal(sig),sig);

      //ctrl+c信号的恢复

      signal(SIGINT,SIG_DFL);

      //kill 的恢复

      signal(SIGTERM,SIG_DFL);

}

 

void testSignal()

{

      printf("pid:%d\n",(int)getpid());

      printf("test signal!\n");

     

      //ctrl+c信号的处理

      signal(SIGINT,fun);

      //kill 的忽略

      signal(SIGTERM,SIG_IGN);

 

      while(1);

}

 

ctrl+c,kill命令,第二次才有响应。