处理信号有三种类型:进程接收到信号后退出;进程忽略该信号;进程收到信号后执行用户设定用系统调用signal的函数。
一、进程接收到信号后退出,一般是系统默认的处理方式。
默认处理方式见下:
SIGHUP 1 A 终端挂起或者控制进程终止
SIGINT 2 A 键盘中断(如break键被按下)
SIGQUIT 3 C 键盘的退出键被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)发出的退出指令
SIGFPE 8 C 浮点异常
SIGKILL 9 AEF Kill信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道
SIGALRM 14 A 由alarm(2)发出的信号
SIGTERM 15 A 终止信号
SIGUSR1 30,10,16 A 用户自定义信号1
SIGUSR2 31,12,17 A 用户自定义信号2
SIGCHLD 20,17,18 B 子进程结束信号
SIGCONT 19,18,25 进程继续(曾被停止的进程)
SIGSTOP 17,19,23 DEF 终止进程
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键
SIGTTIN 21,21,26 D 后台进程企图从控制终端读
SIGTTOU 22,22,27 D 后台进程企图从控制终端写
处理动作一项中的字母含义如下
A 缺省的动作是终止进程
B 缺省的动作是忽略此信号,将该信号丢弃,不做处理
C 缺省的动作是终止进程并进行内核映像转储(dump core),内核映像转储是指将进程数据在内存的映像和进程在内核结构中的部分内容以一定格式转储到文件系统,并且进程退出执行,这样做的好处是为程序员提供了方便,使得他们可以得到进程当时执行时的数据值,允许他们确定转储的原因,并且可以调试他们的程序。
D 缺省的动作是停止进程,进入停止状况以后还能重新进行下去,一般是在调试的过程中(例如ptrace系统调用)
E 信号不能被捕获
F 信号不能被忽略
二、进程忽略该信号。
当进程接收到一个它忽略的信号时,进程丢弃该信号,就象没有收到该信号似的继续运行。一般使用signal函数比较简单。
例:signal(SIGPIPE, SIG_IGN);
三、进程收到信号后执行用户设定用系统调用signal的函数。
进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行用户定义的函数。而且执行用户定义的函数的方法很巧妙,内核是在用户栈上创建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程从内核返回弹出栈顶时就返回到用户定义的函数处,从函数返回再弹出栈顶时,才返回原先进入内核的地方。这样做的原因是用户定义的处理函数不能且不允许在内核态下执行(如果用户定义的函数在内核态下运行的话,用户就可以获得任何权限)。
例:
void setup_signal_handlers(void) { struct sigaction act; act.sa_handler = signal_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); sigaction(SIGHUP, &act, NULL); sigaction(SIGPIPE, &act, NULL); sigaction(SIGTERM, &act, NULL); } void signal_handler(int signum) { switch (signum){ case SIGINT: printf("signum=SIGINT"); break; case SIGHUP: printf("signum=SIGHUP"); break; case SIGQUIT: printf("signum=SIGQUIT"); break; case SIGPIPE: printf("signum=SIGPIPE"); break; case SIGTERM: printf("signum=SIGTERM "); break; } }
1、软中断是在从内核态返回用户态时进行处理的,只用处理完信号才会返回用户态。
2、软中断分可靠不可靠,实时非实时,可靠实时的信号都是大于等于SIGRTMIN,小于等于SIGRTMAX。不可靠非实时信号为1-32
详细见:http://www.cnblogs.com/hoys/archive/2012/08/19/2646377.html