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 }
测试结果:
从测试结果能看出,代码中出现的一次浮点上溢并没有发出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 }
测试结果:
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 }
运行结果:
结果分析:
程序运行后打印了两遍“SIGUSR1 signal captured. value = 10”,其中第1遍是调用raise给自己发送的,第2遍是子进程通过kill函数发送的。