Linux訊號入門詳解
以下是維基百科對訊號的定義:
在電腦科學中,訊號(英語:Signals)是Unix、類Unix以及其他POSIX相容的作業系統中程序間通訊的一種有限制的方式。它是一種非同步的通知機制,用來提醒程序一個事件已經發生。當一個訊號傳送給一個程序,作業系統中斷了程序正常的控制流程,此時,任何非原子操作都將被中斷。如果程序定義了訊號的處理函式,那麼它將被執行,否則就執行預設的處理函式。
簡單的理解訊號就是一種Linux環境下程序通訊的一種機制。
二、訊號從哪來?一般情況下,訊號的來源可分為以下三種:
- 硬體方式:除數為零、無效的儲存訪問等硬體異常產生訊號。這些事件通常由硬體(如:CPU)
- 軟體方式:使用者在終端下呼叫kill命令向程序傳送任務訊號、程序呼叫kill或sigqueue函式傳送訊號、當檢測到某種軟體條件已經具備時發出訊號,如由alarm或settimer設定的定時器超時時將生成SIGALRM訊號等多種情景均可產生訊號。
- 鍵盤輸入:當用戶在終端上按下某鍵時,將產生訊號。如按下組合鍵Ctrl+C將產生一個SIGINT訊號,Ctrl+\產生一個SIGQUIT訊號等。
在Shell下輸入kill –l 可顯示Linux 系統支援的全部訊號,如下表所示:
可以看到Linux中系統一共支援64種訊號,其中1到31號訊號為普通訊號(也程為不可靠訊號),34到64為實時訊號(可靠訊號)。
- 可靠訊號與不可靠訊號的區別:
- 這裡的不可靠主要是不支援訊號佇列,就是當多個訊號發生在程序中的時候(收到訊號的速度超過程序處理的速度的時候),這些沒來的及處理的訊號就會被丟掉,僅僅留下一個訊號。
- 可靠訊號是多個訊號傳送到程序的時候(收到訊號的速度超過程序處理訊號的速度的時候),這些沒來的及處理的訊號就會排入程序的佇列。等程序有機會來處理的時候,依次再處理,訊號不丟失。
我們平時可以接觸的是普通訊號,其各個訊號的含義如下:
- SIGHUP :當用戶退出Shell時,由該Shell啟的發所有程序都退接收到這個訊號,預設動作為終止程序。
- SIGINT :使用者按下組合鍵時,使用者端時向正在執行中的由該終端啟動的程式發出此訊號。預設動作為終止程序。
- SIGQUIT :當用戶按下組合鍵時產生該訊號,使用者終端向正在執行中的由該終端啟動的程式發出此訊號。預設動作為終止程序併產生core檔案。
- SIGILL :CPU檢測到某程序執行了非法指令。預設動作為終止程序併產生core檔案。
- SIGTRAP:該訊號由斷點指令或其他trap指令產生。預設動作為終止程序併產生core檔案。
- SIGABRT :呼叫abort函式時產生該訊號。預設動作為終止程序併產生core檔案。
- SIGBUS:非法訪問記憶體地址,包括記憶體地址對齊(alignment)出錯,預設動作為終止程序併產生core檔案。
- SIGFPE:在發生致命的算術錯誤時產生。不僅包括浮點執行錯誤,還包括溢位及除數為0等所有的算術錯誤。預設動作為終止程序併產生core檔案。
- SIGKILL :無條件終止程序。本訊號不能被忽略、處理和阻塞。預設動作為終止程序。它向系統管理員提供了一種可以殺死任何程序的方法。
- SIGUSR1:使用者定義的訊號,即程式可以在程式中定義並使用該訊號。預設動作為終止程序。
- SIGSEGV:指示程序進行了無效的記憶體訪問。預設動作為終止程序並使用該訊號。預設動作為終止程序。
- SIGUSR2:這是另外一個使用者定義訊號,程式設計師可以在程式中定義並使用該訊號。預設動作為終止程序。
- SIGPIPE :Broken pipe:向一個沒有讀端的管道寫資料。預設動作為終止程序。
- SIGALRM :定時器超時,超時的時間由系統呼叫alarm設定。預設動作為終止程序。
- SIGTERM :程式結束(terminate)訊號,與SIGKILL不同的是,該訊號可以被阻塞和處理。通常用來要求程式正常退出。執行Shell命令kill時,缺少產生這個訊號。預設動作為終止程序。
- SIGCHLD :子程式結束時,父程序會收到這個訊號。預設動作為忽略該訊號。
- SIGCONT:讓一個暫停的程序繼續執行。
- SIGSTOP:停止(stopped)程序的執行。注意它和SIGTERM以及SIGINT的區別:該程序還未結束,只是暫停執行。本訊號不能被忽略、處理和阻塞。預設作為暫停程序。
- SIGTSTP:停止程序的動作,但該訊號可以被處理和忽略。按下組合鍵時發出該訊號。預設動作為暫停程序。
- SIGTTIN:當後臺程序要從使用者終端讀資料時,該終端中的所有程序會收到SIGTTIN訊號。預設動作為暫停程序。
- SIGTTOU:該訊號類似於SIGTIN,在後臺程序要向終端輸出資料時產生。預設動作為暫停程序。
- SIGURG :套接字(socket)上有緊急資料時,向當前正在執行的程序發出此訊號,報告有緊急資料到達。預設動作為忽略該訊號。
- SIGXCPU:程序執行時間超過了分配給該程序的CPU時間,系統產生該訊號併發送給該程序。預設動作為終止程序。
- SIGXFSZ:超過檔案最大長度的限制。預設動作為yl終止程序併產生core檔案。
- SIGVTALRM:虛擬時鐘超時時產生該訊號。類似於SIGALRM,但是它只計算該程序佔有用的CPU時間。預設動作為終止程序。
- SIGPROF:類似於SIGVTALRM,它不僅包括該程序佔用的CPU時間還抱括執行系統呼叫的時間。預設動作為終止程序。
- SIGWINCH:視窗大小改變時發出。預設動作為忽略該訊號。
- SIGIO:此訊號向程序指示發出一個非同步IO事件。預設動作為忽略。
- SIGPWR:關機。預設動作為終止程序。
上面標註出來的訊號是我們在學習過程中重點關注的訊號,在Linux後期的學習中這些訊號的身影將經常出現。
三、訊號的優先順序訊號實質上是軟中斷,中斷有優先順序,訊號也有優先順序。如果一個程序有多個未決訊號,則對於同一個未決的實時訊號,核心將按照發送的順序來遞送訊號。如果存在多個未決訊號,則值(或者說編號)越小的越先被遞送。如果即存在不可靠訊號,又存在可靠訊號(實時訊號),雖然POSIX對這一情況沒有明確規定,但Linux系統和大多數遵循POSIX標準的作業系統一樣,將優先遞送不可靠訊號。
四、訊號的響應方式有哪些?當訊號發生時,使用者可以要求程序以下列3種方式之一對訊號做出響應。
1、 捕捉訊號:對於要捕捉的訊號,可以為其指定訊號處理函式,訊號發生時該函式自動被呼叫,在該函式內部實現對該訊號的處理。(ps:更多捕捉訊號的細節請看另一篇文章:Linux訊號捕捉及其處理)
2、 忽略訊號:巨集定義為SIG_IGN大多數訊號都可使用這種方式進行處理,但是SIGKILL和SIGSTOP這兩個訊號不能被忽略,同時這兩個訊號也不能被捕獲和阻塞。此外,如果忽略某某些由硬體異常產生的訊號(如非法儲存訪問或除以0),則程序的行為是不可預測的。
3、 按照系統預設方式處理,巨集定義為SIG_DFL。大部分訊號的預設操作是終止程序,且所有的實時訊號的預設動作都是終止程序。
五、各種訊號的預設處理情況程式不可捕獲、阻塞或忽略的訊號有:SIGKILL,SIGSTOP
不能恢復至預設動作的訊號有:SIGILL,SIGTRAP
預設會導致程序流產的訊號有:SIGABRT、SIGBUS、SIGFPE、SIGILL、SIGIOT、SIGQUIT、SIGSEGV、SIGTRAP、SIGXCPU、SIGXFSZ
預設會導致程序退出的訊號有:SIGALRM、SIGHUP、SIGINT、SIGKILL、SIGPIPE、SIGPOLL、SIGPROF、SIGSYS、SIGTERM、SIGUSR1、SIGUSR2、SIGVTALRM
預設會導致程序停止的訊號有:SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU
預設程序忽略的訊號有:SIGCHLD、SIGPWR、SIGURG、SIGWINCH
至此,Linux訊號入門的相關知識已經介紹完了,Linux的處理機制和底層細節請看關於訊號的其他文章。