15) SIGTERM

  kill命令的默认方式就是发出SIGTERM信号,在终端输入kill +PID即可给指定PID的进程发送该信号,测试程序如下:

 1 /**
 2  * filename: signal_15.c
 3  * author: Suzkfly
 4  * date: 2021-02-18
 5  * platform: Ubuntu
 6  *     操作步骤:
 7  *     运行可执行程序,记住打印出来的PID的值,另开一个终端,输入kill +PID命令,
 8  *     观察打印结果。
 9  */
10 #include <stdio.h>
11 #include <signal.h>
12 #include <unistd.h>
13 
14 /* 自定义信号处理函数 */
15 void func(int sig)
16 {
17     switch (sig) {
18         case SIGTERM :
19             printf("SIGTERM 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(SIGTERM, func);
29     if (p == SIG_ERR) {
30         printf("signal failed\n");
31     }
32     
33     printf("PID = %d\n", getpid());
34     
35     while (1) {
36         sleep(1);
37     }
38 
39     return 0;
40 }

测试结果:

 

 (该图白线上部分与下部分是两个不同的终端)

16) SIGSTKFLT

  man手册中对该信号的描述是这样的:Stack fault on coprocessor (unused),翻译过来就是:协处理器上的堆栈异常(未使用)。首先协处理器的堆栈异常,具体是哪种异常没说,另外手册上写的未使用,那就算出现了协处理器堆栈异常它也不一定能引发该信号。

17) SIGCHLD

  该信号由子进程停止(stopped)或者终止时产生,实际上子进程从停止态转变为运行态也会引发SIGCHIL信号。进行该项测试需要知道两个命令,一是让进程进入停止态,使用kill -STOP +PID,二是让进程从停止态变回运行态,使用kill -CONT +PID。

  测试程序如下:

 1 /**
 2  * filename: signal_17.c
 3  * author: Suzkfly
 4  * date: 2021-02-18
 5  * platform: Ubuntu
 6  *     操作步骤:另开1个终端,根据子进程打印出来的PID值,可以使用kill -9 +PID杀
 7  *         死子进程,也可以使用kill -STOP +PID,让子进程进入停止态,使用
 8  *         kill -CONT +PID让进程继续运行,观察打印结果。 
 9  */
10 #include <stdio.h>
11 #include <signal.h>
12 #include <unistd.h>
13 
14 /* 自定义信号处理函数 */
15 void func(int sig)
16 {
17     switch (sig) {
18         case SIGCHLD :
19             printf("SIGCHLD 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(SIGCHLD, func);
32         if (p == SIG_ERR) {
33             printf("signal failed\n");
34         }
35         
36         while (1) {
37             printf("I'm parent PID = %d\n", getpid());
38             sleep(5);
39         }
40     } else if (pid == 0) {      /* 子进程 */
41         while (1) {
42             printf("I'm child PID = %d\n", getpid());
43             sleep(5);
44         }
45     }
46 
47     return 0;
48 }

操作过程:

  执行程序,能看到父进程和子进程每隔5秒打印他们自己的PID,另开1个终端,使用kill -STOP命令让子进程停止,这时父进程将收到SIGCHLD信号,子进程进入STOP状态,再执行kill -CONT命令可以让子进程恢复,此时父进程还会收到SIGCHLD信号,使用kill -9杀死子进程,父进程依然能收到SIGCHLD信号。

执行结果:

 18,19) SIGCONT,SIGSTOP

  SIGCONT信号是所有信号中唯一一个默认动作为让进程继续运行的信号,正常情况下要让进程继续运行就应该先让进程进入停止态,但是实际上即使进程正在运行也可以给他发送SIGCONT信号,在信号17中已经说过,可以用kill -STOP +PID让进程进入停止态,使用kill -CONT +PID命令让进程继续运行,实际上kill -STOP +PID命令就是给进程发送SIGSTOP信号,而kill -CONT +PID命令就是给进程发送SIGCONT信号需要注意的是SIGSTOP信号不能被忽略、阻塞已经自定义处理方法

  测试程序如下:

 1 /**
 2  * filename: signal_18.c
 3  * author: Suzkfly
 4  * date: 2021-03-14
 5  * platform: Ubuntu
 6  *     操作步骤:运行程序,另开1个终端,根据进程打印出来的PID值,使用
 7  *         kill -STOP +PID,让子进程进入停止态,使用
 8  *         kill -CONT +PID让进程继续运行,观察打印结果。 
 9  */
10 #include <stdio.h>
11 #include <signal.h>
12 #include <unistd.h>
13 
14 /* 自定义信号处理函数 */
15 void func(int sig)
16 {
17     switch (sig) {
18         case SIGCONT :
19             printf("SIGCONT 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     p = signal(SIGCONT, func);
30     if (p == SIG_ERR) {
31         printf("signal failed\n");
32     }
33     
34     while (1) {
35         printf("PID = %d\n", getpid());
36         sleep(5);
37     }
38 
39     return 0;
40 }

测试结果:

 

 注意事项:

  在测试时发现一个很奇怪的问题,当一个进程被kill -STOP命令变为停止态之后再用kill -CONT命令变为运行态,此时该进程用Ctrl+C或者用Ctrl+\都无法终止,而使用kill -INT命令可以使其终止,这说明一个进程被kill -STOP命令变为停止态之后再用kill -CONT命令变为运行态之后,它并不是收不到信号或者对Ctrl+C等Ctrl+\忽略,而是Ctrl+C和Ctrl+\按键产生不了SIGINT信号和SIGQUIT信号了,其原因尚不明确。