Linux的訊號處理

2021-04-24 17:57:20 字數 2142 閱讀 1617

linux為實現訊號處理提供了比較多的介面,看似紛雜,但理清訊號的關係後還是很有條理的。主要分為以下四組,怎麼傳送乙個訊號,收到乙個訊號後做什麼樣的處理,主動等待乙個訊號的發生,對特定訊號只記錄是否發生供以後再處理;四組的api如下(不考慮多執行緒):

傳送訊號 kill, alarm, arise;

安裝訊號 signal, sigaction;

等待訊號 sigsuspend, sigwait,pause;

阻塞訊號 sigfillset, sigemptyset, sigaddset, sigdelset, sigismember, sigprocmask;

傳送訊號, kill, alarm, arise

這是唯一一組由訊號傳送方呼叫的api,其中alarm, arise都是給自己程序產生訊號,而kill是可以從乙個程序傳送乙個訊號到另乙個程序,因為訊號的接收方一般都不做許可權檢查,所以傳送方要有許可權給的接收方傳送訊號訊號才能被傳送,要不然我就可以寫個非法程式,直接使用kill給程序1傳送乙個sigkill訊號的話,你的系統基本也就over了。這個許可權檢查的指導原則按我的理解是,傳送方的有效使用者是否有許可權給接收方的實際使用者傳送訊號來決定。因為,當你執行乙個seteuid程式,這個程式執行時的euid可能不再是ruid了,但是你仍然可以kill它。arise()的實現我猜就是用kill(getpid(), signo)來實現。另外系統核心檢測到一些異常或是狀態改變時也會給程序傳送訊號,如sigintr,sigchild等等。

安裝訊號, signal, sigaction

這組api是決定收到乙個訊號號的處理方法。如果不顯示的安裝乙個訊號的處理方法,系統都有對應的預設處理方法,大多數都是直接終止程式本身. 在richard stevens的apue中說signal的訊號處理需要重新安裝訊號處理方法,但我在fc5下測試,不重新安裝也是可以的,並且正在進行訊號處理時,傳送乙個訊號過去,該訊號也不會丟失,只是暫時阻塞,等前面的訊號處理完後再處理。當然當正在訊號處理時傳送多個訊號過去,訊號處理完後,可能傳遞乙個訊號過去,其它的訊號會丟失。至於直接使用signal安裝訊號,等訊號處理完後是否會重啟被該訊號中斷的慢速系統呼叫,我沒有測試,不得而知。 當然你可以使用sigaction來安裝訊號,並顯示的指明restart標誌,這樣被該訊號中斷的系統呼叫就會自動重啟。sigaction這個api更複雜,功能也更多靈活,可以隨意定製,通過siginfo_t的結構,可以得到很多訊號相關的資訊。我猜現在的linux的signal都是用sigaction封裝來實現的。跟sigaction相比,signal簡單多了,沒理由不用它,當然,你得保證signal的語義不會對你的程式造成衝突。

等待訊號 pause, sigsuspend, sigwait

這組api都是等待訊號的發生,可以根據程式的實際需求來選取。pause只要接收到訊號就會返回,sigsuspend跟sigwait都是只等待某些特定的訊號發生,但sigsuspend是把引數裡的訊號集給阻塞,而sigwait一般是先呼叫sigprocmask把所有的訊號都阻塞,然後再等待sigwait引數裡指定的訊號。通常sigwait用在多執行緒程式裡,主線程把所有訊號都mask掉,然後不同的執行緒用sigwait來等待自己感興趣的訊號。

阻塞訊號 sigfillset, sigemptyset, sigaddset, sigdelset, sigismember, sigprocmask

這一組api最多也最簡單,前面五個api都是對訊號集的操作,用它用得到乙個你想要的訊號集後就可以呼叫sigprocmaks的設定程式的訊號掩碼了。

另外, siglongjmp, sigsetjmp是安全的在訊號處理程式裡跑轉的兩個介面。

最後一些跟訊號處理程式裡的一些注意事項

1、因為訊號會中斷慢速的系統呼叫,所以當系統呼叫失敗時,一定要檢查失敗原因,當被訊號中斷時做出重啟系統呼叫的動作;

2、因為訊號處理有非同步性,所以任何在訊號處理程式裡呼叫了不具可重入性的函式都要小心了。這裡的不具可重入性的函式據括了系統呼叫跟自己定義的函式。

3、在訊號處理程式裡任何可能導致對全域性變理的修改也要小心了,乙個經常被人忽視的就是在訊號處理程式裡呼叫了乙個系統呼叫後可能導致errno的修改。

Linux 訊號處理

用sigcation函式 在標頭檔案signal.h中 來設定自己的訊號處理函式,用法參見 各種訊號參見 寫了個sigint,也就是c c鍵的處理例子 include includestruct sigaction newsigint,oldsigint void signalinthandler ...

linux 訊號處理

linux下的程式,有時候需要在接到一些終止訊號後,進行清理工作再退出。訊號2的處理函式 void signalhandler 2 int signal cleanup exit 2 int main int argc,char argv 處理訊號2 struct sigaction act 2,a...

Linux訊號處理

訊號是一種軟體中斷,程式收到訊號時,就會呼叫相應的處理函式 如果有註冊 void signal int signum,void handler int int 設定訊號處理方式 訊號處理函式原型 void foo int arg 系統定義的訊號有 signals.define sighup1 han...