一、基本概念
1、信号是软件中断。信号提供了一种异步处理事件的方法。
2、每个信号都有一个名字:这些名字都以SIG开头。
例如: SIGABRT是夭折信号,调用abort函数;SIGALRM是闹钟信号,当由alarm函数设置的计时器超时后产生此信号;
3、Linux支持31种不同的信号;但是同时支持由应用程序额外定义的信号,将其作为实时扩展。
4、头文件为: <signal.h>
5、不存在编号为0的信号,kill函数使用编号为0的信号作为试探进程时候存在的作用。
7、SIGINT: Ctrl+C键通常产生中断信号(SIGINT),这是停止一个已失去控制的程序的方法。
8、SIGSEGV: 硬件异常产生信号:除数为0、无效的内存引用等,这些由硬件检测到,产生SIGSEGV信号
9、SIGURG: 网络连接传来带外数据时
10、SIGPIPE: 管道读进程终止后,进程写此管道时产生,SOCK_STREAM类型的socket关闭时也会产生
11、有两类不能忽略和捕捉的信号:
SIGKILL:
SIGSTOP:
不能忽略的原因是: 它们向超级用户提供了使进程终止或停止的可靠方法
12、捕捉信号: 要通知内核在某种信号发生时调用一个用户函数,在用户函数中,可执行用户希望对这种事件进行处理。
例如:
如果捕捉到一个SIGCHLD信号,则表示一个子进程已经终止,所以此信号的捕捉函数可以调用waitpid以取得该子进程的进程ID以及它的的终止状态。
二、信号 种类:
1、重要摘抄:
SIGINT: 当用户按中断键(一般采用DELETE或Ctrl+C)时,终端驱动程序产生此信号并送至前台进程组的每一个进程。当一个进程在运行时失控,特别是产生大量输出时,常用此信号终止它。
SIGTERM: 由kill命令发送的系统默认终止信号
SIGQUIT: 当用户在终端上按退出键(一般采用Ctrl+\)时,产生此信号,并送至前台进程组中的所有进程。此信号不仅会终止前台进程组,同时还会产生一个core文件。
SIGKILL: 这是两个不能忽略和捕捉的信号之一
SIGSTOP: 这是两个不能忽略和捕捉的信号之一:这是一个作业控制信号,用于停止一个进程。
SIGCHLD: 当一个进程终止或者停止时,将SIGCHLD信号发送给其父进程,按系统默认,将忽略此信号。如果父进程希望被告知其子进程的这种状态改变,则应该捕捉此信号。信号捕捉函数中通常要调用一种waitpid函数以取得子进程ID和其终止状态。
SIGHUP: 如果终端接口检测到一个链接断开,则将此信号发送给该终端相关的控制进程(会话首进程)。
2、所有信号:
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
三、signal函数:信号处理程序、信号捕捉函数
#include <signal.h>
void (*signal(int signo, void (*func)(int) ) )(int)
若出错返回SIG_ERR
注:因为signal的语义与实现有关,所以最好使用sigaction函数代替signal函数。
signo:
func的值:(1) 常量SIG_IGN、常量SIG_DEL (2)当捕捉到此信号时要调用的函数的地址。
如果指定SIG_IGN: 表示向内核忽略此信号
如果指定SIG_DEL: 表示捕捉到此信号时采取系统默认动作
四、测试signal函数
程序可运行:
#include <pthread.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <string> pthread_mutex_t g_mut; pthread_cond_t g_cond; std::string msg; void sig_capture( int signo ){ pthread_mutex_lock ( &g_mut ); switch( signo ){ case SIGTERM: printf("DEBUG: now received SIGTERM(\n"); msg = "SIGTERM"; break; case SIGQUIT: printf("DEBUG: now received SIGQUIT\n"); msg = "SIGQUIT"; break; case SIGINT: msg = "SIGINT"; printf("DEBUG: now received SIGINT\n"); break; default: printf("DBEUG: can't identy this signal\n"); } pthread_mutex_unlock ( &g_mut ); pthread_cond_signal( &g_cond ); } int main ( int argc, char *argv[] ){ pthread_mutex_init ( &g_mut, NULL ); pthread_cond_init ( &g_cond, NULL ); if ( signal( SIGTERM, sig_capture ) == SIG_ERR ){ printf("DEBUG: can't catch signal( SIGTERM )\n"); exit(100); } if ( signal( SIGQUIT, sig_capture ) == SIG_ERR ){ printf("DEBUG: can't catch signal( SIGQUIT )\n"); exit(200); } if ( signal( SIGINT, sig_capture ) == SIG_ERR ){ printf("DEBUG: can't catch signal( SIGINT )\n"); exit(300); } pthread_mutex_lock ( &g_mut ); while( msg.empty() ){ printf("DEBUG: now wait signal...\n"); pthread_cond_wait ( &g_cond, &g_mut ); } pthread_mutex_unlock( &g_mut ); printf("DEBUG: now string: %s\n", msg.c_str()); return 0; }