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 的下载地址:请点这里

推荐阅读:

相关推荐