訊號之signal函式

2021-09-08 17:05:08 字數 3012 閱讀 1963

unix系統的訊號機制最簡單的介面是signal函式。signal函式的功能:為指定的訊號安裝乙個新的訊號處理函式。

#include void (*signal(int signo, void (*func)(int)))(int);
複雜原型分開看:void (*signal( int signo, void (*func)(int) ))(int);函式名      :signal函式引數   :int signo, void (*func)(int)

返回值型別:void (*)(int);

signo引數是訊號名(參見:中unix系統訊號signal欄下的訊號名)。func的值是常量sig_ign、常量sig_dfl或當接到此訊號後要呼叫的函式的位址。如果指定sig_ign,則向核心表示忽略此訊號(記住有兩個訊號sigkill和sigstop不能忽略)。如果指定sig_dfl,則表示接到此訊號後的動作是系統預設動作。當指定函式位址時,則在訊號發生時,呼叫該函式,我們稱這種處理為「捕捉」該訊號。稱此函式為訊號處理程式(signal handler)或訊號捕捉函式(signal-catching function)。

signal的返回值是指向之前的訊號處理程式的指標。(之前的訊號處理程式,也就是在執行signal(signo,func)之前,對訊號signo的訊號處理程式)

開頭所示的signal函式原型太複雜了,如果使用下面的typedef,則可使其簡單一些:

typedef void sigfunc(int);

然後,可將signal函式原型寫成:

sigfunc *signal(int,sigfunc *);

如果檢視系統的標頭檔案,則很可能會找到下列形式的宣告:

#define    sig_err        ( void (*) () )-1

#define sig_dfl ( void (*) () )0

#define sig_ign ( void (*) () )1

這些常量可用於代替「指向函式的指標,該函式需要乙個整型引數,而且無返回值」。signal的第二個引數及其返回值就可用它們表示。這些常量所使用的三個值不一定是-1,0和1。但大多數unix系統都使用上面所示的值。

程式清單10-1 捕捉sigusr1和sigusr2的簡單程式

#include "

apue.h

"static

void sig_usr(int); /*

one handler for both signals

*/int

main(

void

)static

void

sig_usr(

int signo) /*

argument is signal number

*/

pause函式,它使呼叫程序在接到乙個訊號前掛起。

我們在後台執行該程式,並且用kill(1)命令將訊號傳送給它。注意,在unix中,殺死(kill)這個術語是不恰當的。kill(1)命令和kill(2)函式只是將乙個訊號送給乙個程序或程序組。訊號是否終止程序則取決於訊號的型別,以及程序是否安排了捕捉該訊號。

因為執行程式清單10-1的程序不捕捉sigterm訊號,而針對該訊號的系統預設動作是終止,所以當該程序傳送sigterm訊號後,該程序就會終止。

1、程式啟動

當執行乙個程式時,所有訊號的狀態都是系統預設或忽略。通常所有訊號都被設定為它們的預設動作,除非呼叫exec的程序忽略該訊號。確切地講,exec函式將原先設定為要捕捉的訊號都更改為它們的預設動作,其他訊號的狀態則不變(對於乙個程序原先要捕捉的訊號,當其執行乙個新程式後,就自然不能再捕捉它了,因為訊號捕捉函式的位址很可能在所執行的新程式檔案中無意義)。

乙個具體的例子是乙個互動式shell如何處理針對後台程序的中斷和退出訊號。對於乙個非作業控制shell,當在後台執行乙個程序時,例如:

cc main.c &

shell自動將後台程序中對中斷和退出訊號的處理方式設定為忽略。於是,當按中斷鍵時就不會影響到後台程序。如果沒有執行這樣的處理,那麼當按中斷鍵時,它不但會終止前台程序,還會終止所有後台程序。

很多捕捉這兩個訊號的互動式程式具有下列形式的**:

void sig_int(int), sig_quit(int

);if(signal(sigint, sig_ign) !=sig_ign)

signal(sigint, sig_int);

if(signal(sigquit, sig_ign) !=sig_ign)

signal(sigquit, sig_quit);

這樣處理後,僅當訊號當前未被忽略時,程序才會捕捉它們。

從signal的這兩種呼叫中也可以看到這種函式的限制:不改變訊號的處理方式就不能確定訊號的當前處理方式

2、程序建立

當乙個程序呼叫fork時,其子程序繼承父程序的訊號處理方式。因為子程序在開始時複製了父程序的儲存映像,所以訊號捕捉函式的位址在子程序中是有意義的。

本篇博文內容摘自《unix環境高階程式設計》(第二版),僅作個人學習記錄所用。關於本書可參考:

訊號之signal函式

unix系統的訊號機制最簡單的介面是signal函式。signal函式的功能 為指定的訊號安裝乙個新的訊號處理函式。include void signal int signo,void func int int 複雜原型分開看 void signal int signo,void func int ...

linux 訊號 signal函式

include include include include include include include signal 函式有iso c定義,因為iso c 不涉及多執行緒 程序組以及終端i o等,所以它對訊號的定義非常含糊,以至於對於unix系統而言毫無作用。最好用sigactioan來代替...

訊號的設定 signal函式

訊號處理方式的主要方法有倆種 一種是使用簡單的signal函式,另一種是sigaction函式一 signal函式 使用signal 函式時,只需要指定訊號型別和訊號處理函式即可。標頭檔案 include 函式原型 typedef void sighandler t int sighandler t...