最近比較多朋友問我常見的信號和一些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 的下載地址:請點這裡