C++ signal
ISO C标准支持的信号
信号名称 | 含义 | 默认行为 |
---|---|---|
SIGABRT | 异常终止信号,一般通过调用abort函数产生 | terminate+core |
SIGINT | 中断信号,一般通过键盘输入ctrl+c 产生 |
terminate |
SIGSEGV | 段错误信号,一般通过访问非法地址产生 | terminate+core |
SIGTERM | 终止信号,kill 命令默认发送该信号 |
terminate |
SIGFPE | 浮点错误信号,比如除0,浮点计算溢出等 | terminate+core |
SIGILL | 错误指令信号 | terminate+core |
处理信号的三种方式
- 忽略信号(SIG_IGN):忽略信号,不做任何处理,但是
SIGKILL
和SIGSTOP
是不可以被忽略和捕捉的,并且最好不要忽略硬件产生的信号,否则行为未定义。 - 捕捉信号(sighandler):捕捉信号,执行指定的动作。
- 默认行为(SIG_DFL):执行信号的默认行为。
signal async safe的系统函数
可靠信号与不可靠信号
signal比sigaction简单,但signal注册的信号在sa_handler被调用之前把会把信号的sa_handler指针恢复,而sigaction注册的信号在处理信号时不会恢复sa_handler指针:
int sig_int(); /* my signal handling function */
...
signal(SIGINT, sig_int); /* establish handler */
...
sig_int()
{
signal(SIGINT, sig_int); /* reestablish handler for next time */
}
上面的代码大部分情况可以正常运行,但一些特殊情况,比如SIGINT
信号触发之后,在执行到sig_int
的重置语句之前,又触发了SIGINT
,这时会执行默认行为——也就是退出函数,就会有问题。
信号值位于SIGRTMIN和SIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。Linux在支持新版本的信号安装函数sigation()以及信号发送函数sigqueue()的同时,仍然支持早期的signal()信号安装函数,支持信号发送函数kill()。
信号的可靠与不可靠只与信号值有关,与信号的发送及安装函数无关。目前linux中的signal()是通过sigation()函数实现的,因此,即使通过signal()安装的信号,在信号处理函数的结尾也不必再调用一次信号安装函数。同时,由signal()安装的实时信号支持排队,同样不会丢失。