Linux的信号处理和实际使用(结合Redis分析)
最近比较多朋友问我常见的信号和一些Linux信号实际的应用。所以,我简单总结一下,让大家对信号有清晰的理解。
我自己写的系统里面,我是直接参考redis的信号处理机制的。
redis是这样处理信号的:
如果系统支持 HAVE_BACKTRACK,即是:
#if defined(__APPLE__) || defined(__linux__) || defined(__sun)
#define HAVE_BACKTRACE 1
#endif
那么redis会用sigsegvHandler函数处理SIGSEGV , SIGBUS , SIGFPE , SIGILL等信号。
否则只用sigtermHandler 处理 SIGTERM ,SIGQUIT 。
我自己系统是这样实现的(分析如上):
void
setupSignalHandlers(void){
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = sigtermHandler;
sigaction(SIGTERM , &act , NULL);
sigaction(SIGQUIT , &act , NULL);
#ifdef HAVE_BACKTRACE
sigemptyset(&act.sa_mask);
act.sa_flags = SA_NODEFER|SA_RESETHAND|SA_SIGINFO;
act.sa_sigaction = sigsegvHandler;
sigaction(SIGSEGV ,&act , NULL);
sigaction(SIGBUS ,&act , NULL);
sigaction(SIGFPE ,&act , NULL);
sigaction(SIGILL ,&act , NULL);
#endif /* HAVE_BACKTRACE */
return;
}
SIGKILL : 用来立即结束程序的运行. 本信号不能被阻塞, 处理和忽略。
SIGTERM : 有两个信号可以停止进程:SIGTERM和SIGKILL。 SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序。在关闭程序之前,您可以结束打开的记录文件和完成正在做的任务。在某些情况下,假 如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。
SIGINT : 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出。
SIGQUIT信号: SIGQUIT 和SIGINT类似, 但由QUIT字符(通常是Ctrl-)来控制. 进程在因收到 SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。
SIGSEGV : 试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据
SIGBUS :非法地址, 包括内存地址对齐(alignment)出错. eg: 访问一个四个字长的整数, 但其地址不是4的倍数.
SIGFPE : 在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误.
SIGILL : 执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也有可能产生这个信号.
(不得不说的是,redis的信号处理机制。非常漂亮。在程序出现错误的时候,可以打印出和valgrind一样有用的信息。不知道大家是怎样想的。反正我的项目如果C代码过3K。我都会加入这个机制的。)
Redis 的详细介绍:请点这里
Redis 的下载地址:请点这里
推荐阅读: