Linux进程间通信3--信号
1.前言
为了理解信号 ,先从我们最熟悉的场景说起:
1.用户输入命令,在Shell下启动一个前台进程。
2.用户按下Ctrl-C,这个键盘输入产生一个硬件中断。
3.如果CPU当前正在执行这个进程的代码,则该进程的用户空间代码暂停执行,CPU从用户态切换到内核态处理硬件中断。
4. 中断驱动程序将Ctrl-C解释成一个SIGINT信号,记在该进程的PCB中(也可以说发送了一个SIGINT信号给该进程)。
5. 当某个时刻要从内核返回到该进程的用户空间代码继续执行之前,首先处理PCB中记录的信号,发现有一个SIGINT信号待处理,而这个信号的默认处理动作是终止进程,所以直接终止进程而不再返回它的用户空间代码执行。
注意,Ctrl-C产生的信号只能发给前台进程。一个命令 后面加个&可以放到后台运行,这样 Shell不必等待进程结束就可以接受新的命令,启动新的进程。
Shell可以同时运行一个前台进 程和任意多个后台进程,只有前台进程才能接到Ctrl-C这种控制键产生的信号。
前台进程 在运行过程中用户随时可能按下Ctrl-C而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到SIGINT信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)的
2. 用kill -l命令可以察看系统定义的信号列表
每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有 定 义#define SIGINT 2。
编号34以上的是实时信号,只讨论编号34以下的信号,不讨论实时信号。
这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有:
man 7 signal
各类信号的说明都有。
3.信号的产生或者发送
3.1 kill函数
3.2 alarm函数
1 #include <unistd.h> 2 #include <sys/types.h> 3 #include <stdlib.h> 4 #include <stdio.h> 5 #include <signal.h> 6 7 static int alarm_fired = 0; 8 9 void ouch(int sig) 10 { 11 alarm_fired = 1; 12 } 13 14 int main() 15 { 16 pid_t pid; 17 pid = fork(); 18 switch(pid) 19 { 20 case -1: 21 perror("fork failed\n"); 22 exit(1); 23 case 0: 24 //子进程 25 sleep(5); 26 //向父进程发送信号 27 kill(getppid(), SIGALRM); 28 exit(0); 29 default:; 30 } 31 //设置处理函数 32 signal(SIGALRM, ouch); 33 while(!alarm_fired) 34 { 35 printf("Hello World!\n"); 36 sleep(1); 37 } 38 if(alarm_fired) 39 printf("\nI got a signal %d\n", SIGALRM); 40 41 exit(0); 42 }

4. 信号的处理
4.1.signal函数:
1 #include <signal.h> 2 void (*signal(int sig, void (*func)(int)))(int);
1 #include <signal.h> 2 #include <stdio.h> 3 void ouch(int sig) 4 { 5 printf("\nOUCH! - I got signal %d\n", sig); 6 //恢复终端中断信号SIGINT的默认行为 7 (void) signal(SIGINT, SIG_DFL); 8 } 9 int main() 10 { 11 //改变终端中断信号SIGINT的默认行为,使之执行ouch函数 12 //而不是终止程序的执行 13 (void) signal(SIGINT, ouch); 14 while(1) 15 { 16 printf("Hello World!\n"); 17 sleep(1); 18 } 19 return 0; 20 }

可以看到,第一次按下终止命令(ctrl+c)时,进程并没有被终止,面是输出OUCH! - I got signal 2,因为SIGINT的默认行为被signal函数改变了,当进程接受到信号SIGINT时,它就去调用函数ouch去处理,注意ouch函数把信号SIGINT的处理方式改变成默认的方式,所以当你再按一次ctrl+c时,进程就像之前那样被终止了。

浙公网安备 33010602011771号