linux訊號處理相關知識
因為要處理最近專案中碰上的多個子程序退出訊號同時到達,導致程式不當產生core的情況,今天我花了時間看了一些關於linux訊號處理的部落格。
總結一下:(知識未經實踐)
1 1 linux訊號分兩種,一種實時訊號(也叫可靠訊號),一種非實時訊號(也叫不可靠訊號)。 2 2 實時訊號之所以是可靠的,因為在程序阻塞該訊號的時間內,發給該程序的所有實時訊號會排隊,而非實時訊號則會合併為一個訊號。(可以這樣理解,同一個不可靠訊號同時產生時,只有一個訊號會被處理,其它的丟棄) 3 3 早期設計的訊號都是不可靠的,我們常見的SIGUSR1、SIGCHILD、SIGINT只有SIGRTMIN(訊號值為34)以後的訊號才是可靠的。4 4 因此,當我們收到多個子程序同時退出的SIGCHLD訊號時,最好迴圈呼叫waitpid,直到確認所以子程序退出已被處理,否則可能導致某些子程序成為殭屍程序 5 5 訊號是可以忽略、捕獲或阻塞的,但SIGSTOP和SIGKILL都是不可忽略、捕獲或阻塞的訊號。另外有一些錯誤訊號是不可阻塞的,如SIGFPE、SIGILL、SIGSEGV、SIGBUS。 6 6 訊號捕獲處理有兩種方式,一種是非同步處理,另一種也是非同步處理。(開玩笑的,另一種是同步處理)我們比較常用的是非同步處理方式,即:註冊一個訊號處理函式,在訊號發生時由核心呼叫。 7 7 非同步處理方法需要注意註冊的訊號處理函式要儘量短,並且不可以呼叫非可重入函式(如printf、malloc、大多數使用使用了全域性或靜態資料結構的函式)。 8 8 注意非可重入函式並非執行緒安全函式,兩者概念不一樣。一般執行緒安全函式都是通過使用鎖來達到執行緒安全的,但如果在訊號處理函式裡面這樣做,很容易導致死鎖。(當獲取鎖之後,未釋放之前又發生訊號函式呼叫即會出現) 9 9 如果你處理某個訊號裡需要消耗比較長的時間,一種推薦的處理方式是在訊息處理函式將該訊號登記到某個處理佇列後立即返回,在主程序函式裡面順序處理。 10 10 接上,在c語言裡面,可以在訊號函式裡面,使用write函式將訊號值寫入一個管道。管道另一端使用select監聽處理。具體可以參考libevent 11 11 訊號是執行緒級的,你可以使用pthread_kill向特定某個執行緒傳送訊號。如果你使用kill函式往某個程序傳送訊號,核心會隨機將訊號發給一個未阻塞該訊號的執行緒處理。12 12 在多執行緒應用中,我們需要使用sigaction來代替singal函式,並且可以使用pthread_sigmask來為每個執行緒設定獨立的訊號掩碼。 13 13 多執行緒應用中,有一種同步處理訊號的方式:開闢一個執行緒專門負責處理訊號,其它執行緒把訊號都遮蔽掉。訊號處理執行緒迴圈呼叫sigwait等待訊號到來並處理。
(直接貼上文字變成一行,所以使用插入程式碼的方式)
14 Linux支援的訊號列表如下。很多訊號是與機器的體系結構相關的
訊號值 預設處理動作 發出訊號的原因
SIGHUP 1 A 終端掛起或者控制程序終止
SIGINT 2 A 鍵盤中斷(如break鍵被按下)
SIGQUIT 3 C 鍵盤的退出鍵被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)發出的退出指令
SIGFPE 8 C 浮點異常
SIGKILL 9 AEF Kill訊號
SIGSEGV 11 C 無效的記憶體引用
SIGPIPE 13 A 管道破裂: 寫一個沒有讀埠的管道
SIGALRM 14 A 由alarm(2)發出的訊號
SIGTERM 15 A 終止訊號
SIGUSR1 30,10,16 A 使用者自定義訊號1
SIGUSR2 31,12,17 A 使用者自定義訊號2
SIGCHLD 20,17,18 B 子程序結束訊號
SIGCONT 19,18,25 程序繼續(曾被停止的程序)
SIGSTOP 17,19,23 DEF 終止程序
SIGTSTP 18,20,24 D 控制終端(tty)上按下停止鍵
SIGTTIN 21,21,26 D 後臺程序企圖從控制終端讀
SIGTTOU 22,22,27 D 後臺程序企圖從控制終端寫
處理動作一項中的字母含義如下
A 預設的動作是終止程序
B 預設的動作是忽略此訊號,將該訊號丟棄,不做處理
C 預設的動作是終止程序並進行核心映像轉儲(dump core),核心映像轉儲是指將程序資料在記憶體的映像和程序在核心結構中的部分內容以一定格式轉儲到檔案系統,並且程序退出執行,這樣做的好處是為程式設計師提供了方便,使得他們可以得到程序當時執行時的資料值,允許他們確定轉儲的原因,並且可以除錯他們的程式。
D 預設的動作是停止程序,進入停止狀況以後還能重新進行下去,一般是在除錯的過程中(例如ptrace系統呼叫)
E 訊號不能被捕獲
F 訊號不能被忽略
參考文章: https://www.cnblogs.com/WangBoBlog/p/8081284.html Linux 的訊號和執行緒 https://blog.csdn.net/xwc583413343/article/details/55106337 訊號註冊函式回收子程序,waitpid非阻塞回收 https://blog.csdn.net/hacode/article/details/43483057 Linux 實時訊號程式中鎖的探索 https://blog.csdn.net/yusiguyuan/article/details/14229017 Linux 多執行緒應用中如何編寫安全的訊號處理函式 https://www.cnblogs.com/hoys/archive/2012/08/19/2646377.html Linux訊號(signal) 機制分析