这是在网易云课堂学习Linux下的signal()函数的笔记,课程链接:https://study.163.com/course/courseLearn.htm?courseId=1002913011&share=1&shareId=1024164580#/learn/video?lessonId=1003302216&courseId=1002913011
1. 函数原型
可通过man signal命令查看。
signum:要登记的信号值
handler:信号处理函数指针,可以是自定义的信号处理函数,或者SIG_IGN(忽略信号),或者SIG_DFL(采用系统默认方式处理信号)。
系统中有很多信号,每种信号都有一个宏定义,在/usr/include/bits/signum.h 文件中进行的定义。或者使用kill -l可以查看有哪些信号。
我们平时用的命令“kill -9 进程号”就是向系统发送了一个SIGKILL信号。
#define SIGKILL 9 /* Kill, unblockable (POSIX). */
2. 信号的处理
进程可以通过三种方式来响应和处理一个信号:
1)忽略信号
SIGKILL和SIGSTOP永远不能被忽略;
忽略硬件异常;
进程启动时SIGUSR1和SIGUSR2两个信号被忽略。
2)执行默认操作
每个信号有默认动作,大部分信号默认动作是终止信号。
3)捕获信号
告诉内核出现信号时调用自己的处理函数;
SIGKILL和SIGSTOP不能被捕获。
3. 测试代码
下面的测试代码是对两种信号使用自己定义的信号处理函数进行处理,这两种信号分别是:
#define SIGINT 2 /* Interrupt (ANSI). 按ctrl+c产生*/
#define SIGTSTP 20 /* Keyboard stop (POSIX). 按ctrl+z产生*/
代码如下:
1 #include <signal.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 5 // 定义信号处理函数 6 // signo:捕获到的信号 7 void sig_handler(int signo) 8 { 9 printf("%d: %d occured\n", getpid(), signo); 10 } 11 12 13 int main(void) 14 { 15 // 向内核登记信号处理函数及信号值 16 if (signal(SIGTSTP, sig_handler) == SIG_ERR) { 17 perror("signal sigtstp error"); 18 } 19 if (signal(SIGINT, sig_handler) == SIG_ERR) { 20 perror("signal sigint error"); 21 } 22 23 int i = 0; 24 while (i < 30) { 25 printf("%d, %d\n", getpid(), i++); 26 sleep(1); 27 } 28 29 return 0; 30 }
测试结果:
4. 其它测试1
我们将signal()相关的代码注释掉,来进行测试:
#include <signal.h> #include <stdlib.h> #include <stdio.h> // 定义信号处理函数 // signo:捕获到的信号 void sig_handler(int signo) { printf("%d: %d occured\n", getpid(), signo); } int main(void) { // 向内核登记信号处理函数及信号值 // if (signal(SIGTSTP, sig_handler) == SIG_ERR) { // perror("signal sigtstp error"); // } // if (signal(SIGINT, sig_handler) == SIG_ERR) { // perror("signal sigint error"); // } int i = 0; while (i < 30) { printf("%d, %d\n", getpid(), i++); sleep(1); } return 0; }
测试结果:
可以看出,系统对SIGINT信号的默认处理方式是终止程序的运行,对SIGTSTP信号的默认处理方式是暂停程序的运行。
我们可以使用SIGCONT信号来让程序继续运行:kill -SIGCONT 3131。
5. 其它测试2
使用忽略的方式SIG_IGN来处理信号:
1 #include <signal.h> 2 #include <stdlib.h> 3 #include <stdio.h> 4 5 // 定义信号处理函数 6 // signo:捕获到的信号 7 void sig_handler(int signo) 8 { 9 printf("%d: %d occured\n", getpid(), signo); 10 } 11 12 13 int main(void) 14 { 15 // 向内核登记信号处理函数及信号值 16 if (signal(SIGTSTP, sig_handler) == SIG_ERR) { 17 perror("signal sigtstp error"); 18 } 19 if (signal(SIGINT, SIG_IGN) == SIG_ERR) { 20 perror("signal sigint error"); 21 } 22 23 int i = 0; 24 while (i < 30) { 25 printf("%d, %d\n", getpid(), i++); 26 sleep(1); 27 } 28 29 return 0; 30 }
测试结果:
可以看出,使用忽略方式并没有捕获到信号SIGINT,SIG_IGN方式把SIGINT忽略掉了。