一、信号
信号是很短的信息,可以被发送到一个进程或者一组进程。发送给进程唯一信息通常是一个数,以此来标识信号。在标准信号中,对参数、消息或者其他的相随信息没有给予关注。
首先我们来了解一下Linux下的信号机制。
Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,信号值小于SIGRTMIN的信号都是不可靠信号。这就是"不可靠信号"的来源,它的主要问题是信号可能丢失。随着时间的发展,实践证明了有必要对信号的原始机制加以改进和扩充。由于原来定义的信号已有许多应用,不好再做改动,最终只好又新增加了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丢失。我们可以使用 kill -l 命令查看当前系统支持的信号,需要注意的是不同的系统支持的信号是不一样的:
kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
用的比较多的,需要知道的:
使用信号一般有两个目的:
- 让进程知道已经发生了一个特定的事件;
- 强迫进程执行它自己代码中的信号处理程序。
信号值位于SIGRTMIN和SIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。对于目前linux的两个信号安装函数:==signal()及sigaction()==来说,它们都不能把SIGRTMIN以前的信号变成可靠信号(都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对SIGRTMIN以后的信号都支持排队。这两个函数的最大区别在于,经过sigaction安装的信号都能传递信息给信号处理函数,而经过signal安装的信号不能向信号处理函数传递信息。对于信号发送函数来说也是一样的。
我们常用到的信号:
二、signal()-安装信号函数
(1)函数原型
Linux下可以用signal()信号安装的函数, 其中signal()函数的原型如下:
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
- 第一个参数指定信号的值,
- 第二个参数指定针对前面信号值的处理,可以忽略该信号(参数设为SIG_IGN);可以采用系统默认方式处理信号(参数设为SIG_DFL);也可以自己实现处理方式(参数指定一个函数地址)。
(2)代码测试
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> int g_sigstop = 0; void signal_stop(int signum) {
if(SIGTERM == signum) {
printf("SIGTERM signal detected\n"); } else if(SIGALRM == signum) {
printf("SIGALRM signal detected\n"); g_sigstop = 1; } } void signal_code(int signum) {
if(SIGINT == signum) {
printf("SIGINT(CTRL+C) signal\n"); } else if(SIGSEGV == signum) {
printf("SIGSEGV signal detected\n"); exit(-1); } } int main(int argc, char *argv[]) {
char *ptr = NULL; signal(SIGTERM, signal_stop);//kill命令终止 signal(SIGALRM, signal_stop);//alarm() signal(SIGSEGV, signal_code);//指针非法操作内存问题 signal(SIGINT, signal_code);//指针非法操作内存问题 printf("Program start running for 20 seconds...\n"); alarm(20); while(!g_sigstop) {
; } printf("Program start stop running...\n"); printf("Invalid pointer operator will raise SIGSEGV signal\n"); /*这是非法地使用了指针,报错段错误,于是会触发SIGSEGV信号,就会打印相关的调用函数*/ *ptr = 'h'; return 0; }
中间运行的二十秒可以使用CTRL+C来验证SIGINT信号。我们打开新的终端执行killall signal
命令可以看到SIGTERM
执行结果:
./signal Program start running for 20 seconds... SIGTERM signal detected SIGTERM signal detected SIGTERM signal detected SIGTERM signal detected ^CSIGINT(CTRL+C) signal ^CSIGINT(CTRL+C) signal ^CSIGINT(CTRL+C) signal ^CSIGINT(CTRL+C) signal ^CSIGINT(CTRL+C) signal ^CSIGINT(CTRL+C) signal ^CSIGINT(CTRL+C) signal SIGALRM signal detected Program start stop running... Invalid pointer operator will raise SIGSEGV signal SIGSEGV signal detected
三、sigaction()-安装信号函数
(1)函数原型
#include <signal.h> int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
(2)代码测试
结合上面的代码进行 sigaction() 信号安装函数的测试:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> int g_sigstop = 0; void signal_stop(int signum) {
if(SIGTERM == signum) {
printf("SIGTERM signal detected\n"); } else if(SIGALRM == signum) {
printf("SIGALRM signal detected\n"); g_sigstop = 1; } } void signal_code(int signum) {
if(SIGBUS == signum) {
printf("SIGBUS signal detected\n"); } else if(SIGILL == signum) {
printf("SIGILL signal detected\n"); } else if(SIGSEGV == signum) {
printf("SIGSEGV signal detected\n"); } exit(-1); } void signal_user(int signum) {
if(SIGUSR1 == signum) {
printf("SIGUSR1 signal detected\n"); } else if(SIGUSR2 == signum) {
printf("SIGUSR2 signal detected\n"); } g_sigstop = 1; } int main(int argc, char *argv[]) {
char *ptr = NULL; struct sigaction sigact,sigign; signal(SIGTERM, signal_stop);//kill命令终止 signal(SIGALRM, signal_stop);//alarm() signal(SIGSEGV, signal_code);//指针非法操作内存问题 /*用户自定义信号,收到之后执行signal_user函数*/ sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigact.sa_handler = signal_user; /*如果是SIGINT(ctrl+z)信号就忽略*/ sigemptyset(&sigign.sa_mask); sigign.sa_flags = 0; sigign.sa_handler = SIG_IGN; sigaction(SIGINT, &sigign, 0); sigaction(SIGUSR1, &sigact, 0); sigaction(SIGUSR2, &sigact, 0); printf("Program start running for 20 seconds...\n"); alarm(20); while(!g_sigstop) {
; } printf("Program start stop running...\n"); printf("Invalid pointer operator will raise SIGSEGV signal\n"); *ptr = 'h'; return 0; }
我们的SIGINT信号被忽视了,我们的KILL信号也接收到了:
./sigaction Program start running for 20 seconds... ^C^C^C^C^CSIGTERM signal detected SIGTERM signal detected SIGTERM signal detected SIGALRM signal detected Program start stop running... Invalid pointer operator will raise SIGSEGV signal SIGSEGV signal detected
今天的文章 信号、以及安装信号signal()与sigaction()函数讲解(实例代码)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/103358.html