信号
概念
信号是软件中断。很多⽐较重要的应⽤程序都需处理信号。信号提供了⼀种处理异步事件的⽅法。每个信号都有⼀个名字。这些名字都以三个字符SIG开头。
查看系统支持的信号
在Linux系统中可以使用kill -l命令来查看系统支持的信号。
信号发生的条件
1) 进程调用kill函数或使用kill命令发送信号给其他进程。
2) 系统内核异常产生的中断。如硬件损坏等等。
信号发生后的处理方式
1) 忽略信号。但是有两种信号是不能被忽略。这两种信号分别是SIGKILL和SIGSTOP。不能忽略的原因是这是进程向超级⽤户提供⼀种使进程终⽌或停⽌的可靠⽅法。
2) 捕捉信号。可以通知内核发生该信号时调用一个用户自定义的函数。
3) 执行系统默认操作。
测试程序
#include<signal.h> #include<stdlib.h> #include<stdio.h> #include<unistd.h> static void sig_usr(int); /* one handler for both signals */ int main(void) { if (signal(SIGKILL, sig_usr) ==SIG_ERR){ printf("%s\n","can't catch SIGKILL"); exit(0); } if (signal(SIGSTOP, sig_usr) ==SIG_ERR){ printf("%s\n","can'tcatch SIGSTOP"); exit(0); } for ( ; ; ) pause(); } static void sig_usr(intsigno) /* argument is signalnumber */ { if (signo == SIGKILL) printf("%s\n","received SIGKILL\n"); else if (signo == SIGSTOP) printf("receivedSIGSTOP\n"); else printf("received signal%d\n", signo); }
从该测试程序可以看出来,SIGKILL和SIGSTOP信号不能被忽略。从上面的例子可以看出来,signal函数不改变信号的处理方式就不能确定信号当前的信号处理方式。信号没调用signal函数来设置处理函数,当发生该信号时就会使用默认的处理方式来处理。
子进程继承父进程的信号处理方式
测试程序
#include <signal.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> static void sig_usr(int); /* one handler for both signals */ int main(void) { if(signal(SIGUSR1, sig_usr) == SIG_ERR){ printf("%s\n","can'tcatch SIGUSR1"); exit(0); } pid_tpid = fork(); if(pid<0){ printf("%s\n","forkerror"); exit(0); }elseif(pid ==0){ printf("%s\n","child"); }else{ printf("%s\n","parents"); } for( ; ; ) pause(); } static void sig_usr(int signo) /* argument is signal number */ { if(signo == SIGUSR1) printf("%d,%s\n",getpid(),"receivedSIGUSR1\n"); elseif (signo == SIGSTOP) printf("receivedSIGSTOP\n"); else printf("receivedsignal %d\n", signo); }
测试结果:
我们首先查看进程的关系,使用ps 命令来查看父子进程的进程ID。如下所示:
[root@localhost signals]# ps -ef | grep sig
root 3262 2748 0 10:54 pts/0 00:00:00 ./sigusr
root 3263 3262 0 10:54 pts/0 00:00:00 ./sigusr
可以看出子进程的ID为3263,当我们使用 kill -USR1 3263在终端发送命令时,可以看到子进程收到了信号并运行了信号处理函数,并且该信号处理函数是从父进程继承过来的。
[root@localhost signals]# ./sigusr
parents
child
3263,received SIGUSR1
总结
1、SIGKILL和SIGSTOP信号不能被忽略。
2、signal函数不改变信号的处理方式就不能确定信号当前的信号处理方式。
3、子进程可以从父进程处继承信号处理方式。