跟結束程序相關的那些訊號
前言
專案中在使用kube-keepalived-vip時遇到了keepalived相關的Bug, 原本計劃測試最新版的keepalived看是否存在同樣的問題. 在將keepalived升級到當前最新版本v2.0.7之後發現每次執行kubectl delete pod <kube-keepalived-vip pod>
都會出現segfault的核心錯誤, 且較大概率會連帶出現keepalived的殭屍程序, 但對比發現通過手動執行kill -9
結束keepalived程序卻沒有這個問題. 翻了一下runc的程式碼發現kubectl delete
實際上(預設情況)是通過發給程序一個SIGTERM的訊號讓其退出, 這就是為什麼手動執行kill -9
沒有出現同樣的問題. 這裡索性整理了一下與結束程序相關的訊號的區別和聯絡.
訊號
- 什麼是訊號
- 訊號是軟體中斷, 很多比較重要的應用程式都需要處理訊號. 訊號提供了一種處理非同步事件的方法. 例如, 終端用於鍵入中斷健, 會通過訊號機制停止一個程式, 或及早終止管道中的下一個程式.
- UNIX系統的早期版本就已經提供訊號機制, 但是這些系統(V7)所提供的訊號模型並不可靠. 訊號可能丟失, 並且在執行臨界區程式碼時, 程序很難關閉所選擇的訊號. 4.3BSD和SVR3對訊號模型都做了修改, 增加了可靠訊號機制. 但是Berkeley和AT&T所做的更改之間並不相容. 幸運的是, POSIX.1對可靠訊號例程進行了標準化.
- 檢視訊號列表
-
在Linux系統當中可直接通過
kill
命令加-l
引數列出所有的訊號, 主要依據標頭檔案/usr/include/linux/signal.h
. - 可以看到所有的訊號都包含一個正整數序號(序號0有特殊用途)和一個以SIG開頭的簡稱
[root@10-10-88-192 ~]# kill -l 1) SIGHUP2) SIGINT3) SIGQUIT4) SIGILL5) SIGTRAP 6) SIGABRT 7) SIGBUS8) SIGFPE9) SIGKILL10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM27) SIGPROF 28) SIGWINCH29) SIGIO30) SIGPWR 31) SIGSYS34) SIGRTMIN35) SIGRTMIN+136) SIGRTMIN+237) SIGRTMIN+3 38) SIGRTMIN+439) SIGRTMIN+540) SIGRTMIN+641) SIGRTMIN+742) SIGRTMIN+8 43) SIGRTMIN+944) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-956) SIGRTMAX-857) SIGRTMAX-7 58) SIGRTMAX-659) SIGRTMAX-560) SIGRTMAX-461) SIGRTMAX-362) SIGRTMAX-2 63) SIGRTMAX-164) SIGRTMAX [root@10-10-88-192 ~]#
結束程序相關的訊號
通過kill -l
可以看到作業系統總共提供了64種訊號, 這裡只列舉了與結束程序相關的幾種訊號, 分別是訊號序號為1、2、3、9、15的SIGHUP、SIGINT、SIGKILL、SIGTERM
-
SIGHUP
-
如果終端介面檢測到一個連線斷開, 則將此訊號送給與該終端相關的控制程序. (與之相關的命令為
nohup
) - 如果終端會話首程序終止, 也產生此訊號. 在這種情況下, 此訊號送給前臺程序組中的每一個程序.
- 通常用此訊號通知守護程序再次讀取它們的配置檔案. 選用SIGHUP的理由是, 守護程序不會有控制終端, 通常絕不會接收到這種訊號.
-
這也是
kube-keepalived-vip
當中reloadkeepalived.conf
的方式
-
如果終端介面檢測到一個連線斷開, 則將此訊號送給與該終端相關的控制程序. (與之相關的命令為
kill -1 <pid>
-
SIGINT
- 使用者按下中斷健(一般採用DELETE或Ctrl+C)時, 終端驅動程式產生此訊號併發送至前臺程序組中的每一個程序.
- 當一個程序組在執行時失控, 特別是當程序正在螢幕上產生大量不需要的輸出時, 常用此訊號終止.
kill -2 <pid>
-
SIGQUIT
kill -3 <pid>
-
SIGKILL
- 強制立即結束程序, 相較於其他訊號, SIGKILL訊號不能夠被程序捕獲, 也不能夠被忽略, 因此總是能夠結束程序(如果不行, 那一定是作業系統的Bug).
- 不能夠阻塞該訊號
- 使用該訊號一定要想清楚後果
kill -9 <pid>
-
SIGTERM
kill
kill -15 <pid>
結束語
很多時候很多莫名其妙的問題或者Bug都是因為我們對一些細節的不理解或者掌握的不夠透徹, 就比如結束一個程序就有這麼多種方式, 你是否每一種方式都能夠說清楚呢? 基礎是否夯實正是從日常工作的小事積累和體現出來.
參考
- https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
- 《Unix環境高階程式設計》
- Linux man page