天天看點

C标準庫<signal.h>實作

signal.h是c标準函數庫中的信号處理部分,

定義了程式執行時如何處理不同的信号。信号用作程序間通信,

報告異常行為(如除零)、使用者的一些按鍵組合(如同時按下ctrl與c鍵,産生信号sigint)。信号是程式執行過程中發生的異常事件,同步信号的産生

是因為程式自身的某些動作,例如除零或不正當的通路存儲器,異步信号是由程式外部的行為引起的,比如有人敲擊了提示鍵或者另外一個程式(異步地執行)給你

的程式發信号,都會引發一個異步信号。程式不能屏蔽的信号要求立即得到處理。如果不對發生的信号指定一種處理方法,那麼它就會被作為一種緻命錯誤對待,然

後程式就會以失敗的狀态終止執行

頭檔案<singal.h>定義了一個無窮信号集的各種編碼值:

兩個函數:

raise函數,報告一個同步信号

signal函數,可以指定一種信号的處理方法

可以通過一下三種方式處理信号:

預設處理是終止程式,就像上面所描述的那樣

信号忽略是直接把它丢棄

信号處理是把控制權移給一個指定的函數

頭檔案 <signal.h>為處理各種各樣的信号聲明了一個類型和兩個函數,并定義了幾個宏

定義的類型是:sig_atomic_t

該類型是整數類型,聲明為這種類型的對象可以作為一個原子實體被通路,即使有異步中斷發生的時候也是如此。

定義的宏有: sig_dfl、sig_err、sig_ign

它們展開為具有不同值的常量表達式,這些表達式的類型和函數signal的第二個參數及傳回值的類型相容,并且它們的值與所有聲明的函數的位址都不相等。

指定信号處理

函數signal:

或聲明成:

signal函數通過3種方式來保證接收到的信号編号sig被依次處理,如果func的值是sig_dfl,那麼會使用預設的信号處理方式;如果

func的值是sig_ign,那麼這個信号就會被忽略;否則,func就指向一個函數,當這個信号發生時,就調用這個函數,這樣的函數就被稱為信号處理

程式。

函數raise:

函數raise把信号sig送給正在執行的程式

傳回值:執行成功傳回0,否則傳回非0

從本質上說,信号處理是不可移植的。隻有當必須指定一個已知的作業系統集的信号處理時,才能使用<signal.h>中聲明的函數,不用費盡心思把代碼變成通用的,這是不可能的

如果對一個信号的預設處理是可行的,那麼就選擇這種處理方法,使用自己的信号處理程式會降低可移植性并且可能導緻程式對信号的誤處理增多,如果必須提供某個信号的處理程式,對其進行分類如下:

不可能傳回值的信号處理程式,e.g:sigfpe和sigabrt

必須傳回值的信号處理程式,e.g:sigint

不能傳回值的信号處理程式最後會調用abort、exit或者longjmp來結束。當然,sigabrt的處理程式不能調用abort來結束。處

理程式不應該調用singal使自己重建。如果程式沒有終止,就把剩下的工作給其他的函數。如果信号是異步的,要注意程式所有的輸入輸出,因為這樣的操作

也會中斷庫的執行。

必須傳回的信号處理程式用一個return語句結束,如果它想讓自己複位,那麼應該在入口處立即傳回。如果信号是異步的,就在一個

sig_atomic_t類型的volatile資料對象中存儲一個非零值。不要執行其他任何對正在執行的程式有副作用的動作,例如輸入輸出和通路其他的

資料對象

下面是一個異步信号處理程式的例子:

這個程式調用signal(sigint, &field_int)來建立處理程式。它會不時地執行下面的代碼來檢查是否發生了異步互動式提示中斷:

 raise.c 

 signal.c

繼續閱讀