一、Linux信号
信号可以在进程间进行传递,Linux的异步通知就是基于信号进行实现的。在Linux中可以使用的信号如下所示:
除了SIGSTOP和SIGKILL信号外,其余信号均能被进程忽略或捕获。
信号的接收:
在用户进程中可以使用signal()函数设置相应的信号处理处理函数。类似于MCU中的中断,当满足触发中断条件的时候,就会去执行相对应的中断处理函数。
signal()函数原型如下:
void (*signal(int signum, void (*handler))(int)))(int);
第一个参数指定信号。 第二个参数指定信号对应的处理函数。
下面编写一个程序验证信号的接收:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4
5 void sigterm_handler(int signo)
6 {
7 printf("\r\nSig N.o is %d\r\n", signo);
8 exit(0);
9 }
10
11 int main()
12 {
13 signal(SIGINT, sigterm_handler);
14
15 while(1);
16 return 0;
17 }
①signal函数的第一个参数是SIGINT,代表的是中端退出
②signal函数指定的第二个参数是信号处理函数sigterm_handler,他会打印接收到的信号值。
编译并运行结果如如所示:
在进程执行的时候,按下ctrl+C就会发送SIGINT信号,因此信号处理函数就会打印messege。
信号实现异步通知:
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <stdio.h>
4 #include <fcntl.h>
5 #include <signal.h>
6 #include <unistd.h>
7
8 #define MAX_LEN 100
9
10 void input_handler(int num)
11 {
12 char data[MAX_LEN];
13 int len;
14
15 /*读取并输出STDIN_FILENO上的输出*/
16 len = read(STDIN_FILENO, &data, MAX_LEN);
17 data[len] = 0; //添加字符串结尾0
18 printf("input data :%s\r\n",data);
19 }
20
21
22 int main()
23 {
24 int oflags;
25
26 /*启动信号驱动机制*/
27 signal(SIGIO, input_handler);
28 fcntl(STDIN_FILENO, F_SETOWN, getpid()); //设置本进程为STDIN_FILENO的所有者
29 oflags = fcntl(STDIN_FILENO, F_GETFL);
30 fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);
31
32 while(1);
33
34
35 return 0;
36 }
本程序对标准输入的文件描述符STDIN_FILENO启动信号机制,每当用户输入时,进程将接收到SIGIO信号,信号处理函数将会被调用打印输入的messege。
验证:
为了能在用户空间处理一个设备的信号,需要完成三个步骤:
① 通过F_SETOWN命令设置文件的拥有者为本进程,只有这样设备文件才知道信号发给谁
② 通过F_SETFL命令设置设备文件为FASYNC,异步通知模式。
③ 通过signal()函数连接信号和信号处理函数。