轉自 https://www.cnblogs.com/gaorong/p/6430905.html
在linux下有很多信號,按可靠性分為可靠信號和非可靠信號,按時間分為實時信號和非實時信號,linux進程也有三種方式來處理收到的信號:
(1)忽略信號,即對信號不做任何處理,其中,有兩個信號不能忽略:SIGKILL及SIGSTOP;
(2)捕捉信號。定義信號處理函數,當信號發生時,執行相應的處理函數;
(3)執行缺省操作,Linux對每種信號都規定了默認操作。
Linux進程對實時信號的缺省反應是進程終止。但是對於高性能服務器編程來說,這是致命的缺陷,對於這類服務器需要保證在收到各種信號后仍然可以可靠運行,所以我們需要在理解各種信號的緣由和正確的處理方式。本文將筆者經常碰到的一些信號進行整理,結合自己的使用經驗簡要分析。
SIGHUP和控制台操作有關,當控制台被關閉時系統會向擁有控制台sessionID的所有進程發送HUP信號,默認HUP信號的action是 exit,如果遠程登陸啟動某個服務進程並在程序運行時關閉連接的話會導致服務進程退出,所以一般服務進程都會用nohup工具啟動(該命令就是讓忽略該信號)或寫成一個 daemon(利用setsid進行)。
以下五組可以放在一塊類比
SIGINT 終止進程,通常我們的Ctrl+C就發送的這個消息。
SIGQUIT 和SIGINT類似, 但由QUIT字符(通常是Ctrl- \ )來控制. 進程收到該消息退出時會產生core文件。
SIGKILL 消息編號為9,我們經常用kill -9來殺死進程發送的就是這個消息,程序收到這個消息立即終止,這個消息不能被捕獲,封鎖或這忽略,所以是殺死進程的終極武器。
SIGTERM 是不帶參數時kill默認發送的信號,默認是殺死進程。
1.SIGINT SIGTERM區別
前者與字符ctrl+c關聯,后者沒有任何控制字符關聯。
前者只能結束前台進程,后者則不是。
2.SIGTERM SIGKILL的區別
前者可以被阻塞、處理和忽略,但是后者不可以。
KILL命令的默認不帶參數發送的信號就是SIGTERM.讓程序有好的退出。
SIGTERM比較友好,進程能捕捉這個信號,根據您的需要來關閉程序。在某些情況下,假如進程正在進行作業而且不能中斷,那么進程可以忽略這個SIGTERM信號。
因為SIGTERM可以被阻塞,所以有的進程不能被結束時,需要用kill發送SIGKILL。即:kill-9 進程號。
SIGSTOP 停止進程的執行,同SIGKILL一樣不可以被應用程序所處理,注意它和terminate以及interrupt的區別:該進程還未結束, 只是暫停執行.由 Ctrl+Z 控制,用戶可以使用使用fg/bg操作恢復執行前台或后台的進程。fg命令在前台恢復執行被掛起的進程,此時可以使用ctrl-z再次掛起該進程,bg命令在后台恢復執行被掛起的進程,而此時將無法使用ctrl-z再次掛起該進程。
SIGCONT 當SIGSTOP發送到一個進程時,通常的行為是暫停該進程的當前狀態。如果發送SIGCONT信號,該進程將僅恢復執行。除了其他目的,SIGSTOP和SIGCONT用於Unix shell中的作業控制,無法捕獲或忽略SIGCONT信號。
SIGPIPE 這個是向一個沒有讀進程的管道寫數據產生的錯誤,這種解釋過於官方。在網絡編程中這個信號發生在如果客戶端已經關閉了套接字, 而服務器調用了一次write,服務器就會收到一個RST segment,如果服務器再次調用write,這個時候就會產生SIGPIPE信號,系統默認的處理方式是關掉這個進程, 但是對於一個高可用的服務器程序來說,需要手動處理這個信號,所以你會看到許多服務器程序代碼會在前面顯式加上signal (SIGPIPE, SIG_IGN)來忽略這個信號。
SIGCHILD 這個同樣是高性能服務器需要關注的信號,如果服務器采用fork產生的子進程推出后要調用wait進行資源回收,防止僵屍進程的產生,但是如果程序對子進程退出后的狀態不感興趣的話可以調用signal(SIGCHLD,SIG_IGN); 交給系統init去回收。子進程也不會產生僵屍進程了。
SIGSEGV 就是SegmentFault 試圖訪問未分配給自己的內存, 或試圖往沒有寫權限的內存地址寫數據,官方舉得三個例子是:
- buffer overflow --- usually caused by a pointer reference out of range. 野指針
- stack overflow --- please keep in mind that the default stack size is 8192K. 棧溢出
- illegal file access --- file operations are forbidden on our judge system. 非法文件訪問
SIGBUS 指針所對應的地址是有效地址,但總線不能正常使用該指針。通常是未對齊的數據訪問所致。試圖訪問一塊無文件內容對應的內存區域,比如超過文件尾的內存區域,或者以前有文件內容對應,現在為另一進程截斷過的內存區域。apache爆出的一個bug就是mmap調用的時候文件發生改變就會爆出這個錯誤,具體參考這篇精彩的博客是 : 由mmap引發的SIGBUS
關於上面兩個信號,《UNP》卷二中對於共享內存mmap引發這兩個錯誤的原因用一張圖描述:
SIGBUS意味着我們是在內存映射區內訪問,但是已超出了底層支撐對象的大小。SIGSEGV則意味着我i們在內存映射區以外訪問。
SIGURG I/O緊急信號,也就是tcp傳輸帶外數據時使用,但是tcp手冊 RFC6093中已經不建議使用緊急指針了,所以這個信號也就沒什么用了。
SIGIO 當描述符上可以進行I/O時產生這個信號,這時五大IO模型中信號驅動IO模型的實現信號。
SIGALRM 時鍾定時信號, 計算的是實際的時間或時鍾時間.alarm函數使用該信號.
以上就是編程中常見到的信號,也是最引人關注的信號,至於其他信號,以后想起再寫吧。
2018.6.14 append:
https://www.linuxjournal.com/article/10815 shell 捕獲信號