Linux系統中的訊號

來源:互聯網
上載者:User

        訊號(Signal)是Linux系統中用於進程之間相互連信或操作的一種機制。訊號是一個相當廣泛的課題;在這裡,我們僅僅探討幾種最重要的訊號以及利用訊號控制進程的技術。
        訊號是一個發送到進程的特殊資訊。訊號機制是非同步;當一個進程接收到一個訊號時,它會立刻處理這個訊號,而不會等待當前函數甚至當前一行代碼結束運行。訊號有幾十種,分別代表著不同的意義。訊號之間依靠它們的值來區分,但是通常在程式中使用訊號的名字來表示一個訊號。在Linux系統中,這些訊號和以它們的名稱命名的常量均定義在/usr/include/bits/signum.h檔案中。(通常程式中不需要直接包含這個標頭檔,而應該包含<signal.h>。)
        當一個進程接收到訊號,基於不同的處理方式(disposition),該進程可能執行幾種不同操作中的一種。每個訊號都有一個預設處理方式(default disposition),當進程沒有指定自己對於某個訊號的處理方式的時候,預設處理方式將被用於對對應訊號作出響應。對於多數種類的訊號,程式都可以自由指定一個處理方式——程式可以選擇忽略這個訊號,或者調用一個特定的訊號處理函數。如果指定了一個訊號處理函數,當前程式會暫停當前的執行過程,同時開始執行訊號處理函數,並且當訊號處理函數返回之後再從被暫停處繼續執行。
        Linux系統在運行中出現特殊狀況的時候也會向進程發送訊號通知。例如,當一個進程執行非法操作的時候可能會收到SIGBUS(主線錯誤),SIGSEGV(段溢出錯誤)及SIGFPE(浮點異常)這些訊號。這些訊號的預設處理方式都是終止程式並且產生一個核心轉儲檔案(core file)。
一個進程除了響應系統發來的訊號,還可以向其它進程發送訊號。對於這種機制的一個最常見的應用就是通過發送SIGTERM或SIGKILL訊號來結束其它進程。3#3 除此之外,它還常見於向運行中的進程發送命令。兩個“使用者自訂”的訊號SIGUSR1和SIGUSR2就是專門作此用途的。SIGHUP訊號有時也用於這個目的——通常用於喚醒一個處於等待狀態的進程或者使進程重新讀取設定檔。
系統調用sigaction用於指定訊號的處理方式。函數的第一個參數是訊號的值。之後兩個參數是兩個指向sigaction結構的指標;第一個指向了將被設定的處理方式,第二個用於儲存先前的處理方式。這兩個sigaction結構中最重要的都是sa_handler域。它可以是下面三個值:

· SIG_DFL,指定預設的訊號處理方式· SIG_IGN,指定該訊號將被忽略· 一個指向訊號處理函數的指標。這個函數應該接受訊號值作為唯一參數,且沒有傳回值。

        因為訊號處理是非同步進行的,當訊號處理函數被調用的時候,主程式可能處在非常脆弱的狀態,並且這個狀態會一直保持到訊號處理函數結束。因此,應該盡量避免在訊號處理函數中使用輸入輸出功能、絕大多數庫函數和系統調用。
        訊號處理函數應該做儘可能少的工作以響應訊號的到達,然後返回到主程式中繼續運行(或者結束進程)。多數情況下,所進行的工作只是記錄訊號的到達。而主程式則定期檢查是否有訊號到達,並且針對當時情況作出相應的處理。
       訊號處理函數也可能被其它訊號的到達所打斷。雖然這種情況聽起來非常罕見,一旦出現,程式將非常難以確定問題並進行調試。甚至於對全域變數賦值可能也是不安全的,因為一個賦值操作可能由兩個或更多機器指令完成,而在這些指令執行期間可能會有第二個訊號到達,致使被修改的全域變數處於不完整的狀態。如果你需要從訊號處理函數中設定全域標誌以記錄訊號的到達,這個標誌必須是特殊類型sig_atomic_t的執行個體。Linux保證對於這個類型變數的賦值操作只需要一條機器指令,因此不用擔心可能在中途被打斷。在Linux系統中,sig_atomic_t就是基本的int類型;事實上,對int或者更小的整型變數以及指標賦值的操作都是原子操作。不過,如果你希望所寫的程式可以向任何標準UNIX系統移植,則應將所有全域變數設為sig_atomic_t類型。
        如下所示,代碼清單3.5中的簡單程式中,我們利用訊號處理函數統計程式在運行期接收到SIGUSR1訊號的次數。SIGUSR1訊號是一個為應用程式保留的訊號。
        代碼清單 3.5 (sigusr1.c)使用訊號處理函數

#include <signal.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <unistd.h>sig_atomic_t sigusr1_count = 0;void handler(int signal_number){++sigusr1_count;}int main (){struct sigaction sa;memset (&sa, 0, sizeof (sa));sa.sa_handler = &handler;sigaction (SIGUSR1, &sa, NULL);/* 這裡可以執行一些長時間的工作。*/sleep(20);printf ("SIGUSR1 was raised %d times\n", sigusr1_count);return 0;}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.