1. 程式人生 > >Linux訊號入門詳解

Linux訊號入門詳解

一、什麼是訊號?

以下是維基百科對訊號的定義:

在電腦科學中,訊號英語Signals)是Unix類Unix以及其他POSIX相容的作業系統中程序間通訊的一種有限制的方式。它是一種非同步的通知機制,用來提醒程序一個事件已經發生。當一個訊號傳送給一個程序,作業系統中斷了程序正常的控制流程,此時,任何非原子操作都將被中斷。如果程序定義了訊號的處理函式,那麼它將被執行,否則就執行預設的處理函式。

簡單的理解訊號就是一種Linux環境下程序通訊的一種機制。

二、訊號從哪來?

一般情況下,訊號的來源可分為以下三種:

  1. 硬體方式:除數為零、無效的儲存訪問等硬體異常產生訊號。這些事件通常由硬體(:CPU)
    檢測到,並將其通知給Linux作業系統核心,然後核心生成相應的訊號,並把訊號傳送給該事件發生時正在進行的程式。
  2. 軟體方式:使用者在終端下呼叫kill命令向程序傳送任務訊號、程序呼叫killsigqueue函式傳送訊號、當檢測到某種軟體條件已經具備時發出訊號,如由alarmsettimer設定的定時器超時時將生成SIGALRM訊號等多種情景均可產生訊號。
  3. 鍵盤輸入:當用戶在終端上按下某鍵時,將產生訊號。如按下組合鍵Ctrl+C將產生一個SIGINT訊號,Ctrl+\產生一個SIGQUIT訊號等。
二、訊號都有哪些種類?

Shell下輸入kill –l 可顯示Linux 系統支援的全部訊號,如下表所示:

訊號列表

可以看到Linux中系統一共支援64種訊號,其中1到31號訊號為普通訊號(也程為不可靠訊號),34到64為實時訊號(可靠訊號)。

  • 可靠訊號與不可靠訊號的區別:
    • 這裡的不可靠主要是不支援訊號佇列,就是當多個訊號發生在程序中的時候(收到訊號的速度超過程序處理的速度的時候),這些沒來的及處理的訊號就會被丟掉,僅僅留下一個訊號。
    • 可靠訊號是多個訊號傳送到程序的時候(收到訊號的速度超過程序處理訊號的速度的時候),這些沒來的及處理的訊號就會排入程序的佇列。等程序有機會來處理的時候,依次再處理,訊號不丟失。

我們平時可以接觸的是普通訊號,其各個訊號的含義如下:

  1.  SIGHUP :當用戶退出Shell時,由該Shell啟的發所有程序都退接收到這個訊號,預設動作為終止程序。
  2.  SIGINT :使用者按下組合鍵時,使用者端時向正在執行中的由該終端啟動的程式發出此訊號。預設動作為終止程序。
  3.  SIGQUIT :當用戶按下組合鍵時產生該訊號,使用者終端向正在執行中的由該終端啟動的程式發出此訊號。預設動作為終止程序併產生core檔案。
  4.  SIGILL  :CPU檢測到某程序執行了非法指令。預設動作為終止程序併產生core檔案。
  5. SIGTRAP:該訊號由斷點指令或其他trap指令產生。預設動作為終止程序併產生core檔案。
  6.  SIGABRT :呼叫abort函式時產生該訊號。預設動作為終止程序併產生core檔案。
  7. SIGBUS:非法訪問記憶體地址,包括記憶體地址對齊(alignment)出錯,預設動作為終止程序併產生core檔案。
  8. SIGFPE:在發生致命的算術錯誤時產生。不僅包括浮點執行錯誤,還包括溢位及除數為0等所有的算術錯誤。預設動作為終止程序併產生core檔案。
  9.  SIGKILL :無條件終止程序。本訊號不能被忽略、處理和阻塞。預設動作為終止程序。它向系統管理員提供了一種可以殺死任何程序的方法。
  10. SIGUSR1:使用者定義的訊號,即程式可以在程式中定義並使用該訊號。預設動作為終止程序。
  11. SIGSEGV:指示程序進行了無效的記憶體訪問。預設動作為終止程序並使用該訊號。預設動作為終止程序。
  12. SIGUSR2:這是另外一個使用者定義訊號,程式設計師可以在程式中定義並使用該訊號。預設動作為終止程序。
  13.  SIGPIPE :Broken pipe:向一個沒有讀端的管道寫資料。預設動作為終止程序。
  14.  SIGALRM :定時器超時,超時的時間由系統呼叫alarm設定。預設動作為終止程序。
  15.  SIGTERM :程式結束(terminate)訊號,與SIGKILL不同的是,該訊號可以被阻塞和處理。通常用來要求程式正常退出。執行Shell命令kill時,缺少產生這個訊號。預設動作為終止程序。
  16.  SIGCHLD :子程式結束時,父程序會收到這個訊號。預設動作為忽略該訊號。
  17. SIGCONT:讓一個暫停的程序繼續執行。
  18. SIGSTOP:停止(stopped)程序的執行。注意它和SIGTERM以及SIGINT的區別:該程序還未結束,只是暫停執行。本訊號不能被忽略、處理和阻塞。預設作為暫停程序。
  19. SIGTSTP:停止程序的動作,但該訊號可以被處理和忽略。按下組合鍵時發出該訊號。預設動作為暫停程序。
  20. SIGTTIN:當後臺程序要從使用者終端讀資料時,該終端中的所有程序會收到SIGTTIN訊號。預設動作為暫停程序。
  21. SIGTTOU:該訊號類似於SIGTIN,在後臺程序要向終端輸出資料時產生。預設動作為暫停程序。
  22.  SIGURG :套接字(socket)上有緊急資料時,向當前正在執行的程序發出此訊號,報告有緊急資料到達。預設動作為忽略該訊號。
  23. SIGXCPU:程序執行時間超過了分配給該程序的CPU時間,系統產生該訊號併發送給該程序。預設動作為終止程序。
  24. SIGXFSZ:超過檔案最大長度的限制。預設動作為yl終止程序併產生core檔案。
  25. SIGVTALRM:虛擬時鐘超時時產生該訊號。類似於SIGALRM,但是它只計算該程序佔有用的CPU時間。預設動作為終止程序。
  26. SIGPROF:類似於SIGVTALRM,它不僅包括該程序佔用的CPU時間還抱括執行系統呼叫的時間。預設動作為終止程序。
  27. SIGWINCH:視窗大小改變時發出。預設動作為忽略該訊號。
  28. SIGIO:此訊號向程序指示發出一個非同步IO事件。預設動作為忽略。
  29. 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的處理機制和底層細節請看關於訊號的其他文章。