进程间通信之——信号复现(8~10)(四)

8) SIGFPE

  该信号由浮点异常导致,实际上当除数为0时就会导致该信号,无论被除数是什么类型的,只要除数是0,就会发出该信号。测试代码如下:

 1 /**
 2  * filename: signal_8.c
 3  * author: Suzkfly
 4  * date: 2021-02-16
 5  * platform: Ubuntu
 6  *     操作步骤:
 7  *     运行可执行程序。
 8  */
 9 #include <stdio.h>
10 #include <signal.h>
11 #include <float.h>
12 #include <stdlib.h>
13 
14 /* 自定义信号处理函数 */
15 void func(int sig)
16 {
17     switch (sig) {
18         case SIGFPE :
19             printf("SIGFPE signal captured. value = %d\n", sig);
20             exit(0);    /* 此处不能去掉,否则会一直进 */
21         break;
22     }
23 }
24 
25 int main(int argc,char *argv[])
26 {
27     int   i = 0;
28     float f = 0;
29     
30     signal(SIGFPE, func);
31     
32     f = FLT_MAX * 2;        /* 浮点上溢 */
33     printf("f = %f\n", f);
34     i = 1/0;
35     //f = 1/0;
36     printf("f = %f\n", f);
37 
38     return 0;
39 }

测试结果:

进程间通信之——信号复现(8~10)(四)

 

   从测试结果能看出,代码中出现的一次浮点上溢并没有发出SIGFPE信号,但是当除数为0时发出了SIGFPE信号。需要注意当自己定义信号处理方式时也要让程序退出,否则会一直触发信号。

9) SIGKILL

  该信号可以在终端使用kill命令发出,具体做法是输入:kill -9 +进程pid

  测试程序如下:

 1 /**
 2  * filename: signal_9.c
 3  * author: Suzkfly
 4  * date: 2021-02-16
 5  * platform: Ubuntu
 6  *     操作步骤:
 7  *     运行可执行程序,发现signal函数的返回值为SIG_ERR,并且用kill -9命令可以将其杀死
 8  */
 9 #include <stdio.h>
10 #include <signal.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 
14 /* 自定义信号处理函数 */
15 void func(int sig)
16 {
17     switch (sig) {
18         case SIGKILL :
19             printf("SIGKILL signal captured. value = %d\n", sig);
20         break;
21     }
22 }
23 
24 int main(int argc,char *argv[])
25 {
26     void(*p)(int) = NULL;
27     
28     p = signal(SIGKILL, func);
29     if (p == SIG_ERR) {
30         printf("signal failed\n");
31     }
32     printf("pid = %d\n", getpid());
33 
34     while (1) {
35         sleep(1);
36     }
37 
38     return 0;
39 }

测试结果:

进程间通信之——信号复现(8~10)(四)

 

 signal信号调用失败,因为SIGKILL信号不能自定义处理方式,并且另开一个终端,输入kill -9 6884,也能正常将进程杀死。之所以留这样的信号就是为了保证不可能会有杀不死的进程。

10) SIGUSR1

  该信号给用户使用的信号,自然是由用户来发送,一般可以用两个函数实现:

10.1 raise

函数原型 int raise(int sig);
头文件 signal.h
功能 给自己发送信号
参数 [in]:sig:要发送的信号
返回 成功返回0,失败返回非0值

10.2 kill

函数原型 int kill(pid_t pid, int sig);
头文件 signal.h
功能 给指定PID的进程发信号
参数

[in]:pid:指定进程的PID

[in]:sig:要发送的信号

返回 成功返回0,失败返回-1

  函数kill虽然名字叫kill,但它的真实意义其实只是给指定PID的进程发送指定信号而已。测试程序如下:

 

 1 /**
 2  * filename: signal_10.c
 3  * author: Suzkfly
 4  * date: 2021-02-16
 5  * platform: Ubuntu
 6  *     操作步骤:
 7  *     运行可执行程序,观察打印信息。
 8  */
 9 #include <stdio.h>
10 #include <signal.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 
14 /* 自定义信号处理函数 */
15 void func(int sig)
16 {
17     switch (sig) {
18         case SIGUSR1 :
19             printf("SIGUSR1 signal captured. value = %d\n", sig);
20         break;
21     }
22 }
23 
24 int main(int argc,char *argv[])
25 {
26     int pid = 0;
27     void(*p)(int) = NULL;
28    
29     pid = fork();
30     if (pid > 0) {  /* 父进程 */
31         p = signal(SIGUSR1, func);
32         if (p == SIG_ERR) {
33             printf("signal failed\n");
34         }
35         raise(SIGUSR1);             /* 给自己发送SIGUSR1信号 */
36         while (1) {
37             sleep(1);
38         }
39     } else if (pid == 0) {          /* 子进程 */
40         sleep(1);                   /* 等待父进程注册信号 */
41         kill(getppid(), SIGUSR1);   /* 向父进程发送SIGUSR1信号 */
42     }
43 
44     return 0;
45 }

运行结果:

  进程间通信之——信号复现(8~10)(四)

 

 结果分析:

  程序运行后打印了两遍“SIGUSR1 signal captured. value = 10”,其中第1遍是调用raise给自己发送的,第2遍是子进程通过kill函数发送的。

进程间通信之——信号复现(8~10)(四)

上一篇:基于vmware安装CentOS 7.9以及集群环境配置


下一篇:安装完整功能的 vim 到 Ubuntu 和 Debian 或 Centos