Linux 中的信號

1、基本概念 


軟中斷信號(signal,又簡稱爲信號)用來通知進程發生了異步事件。進程之間可以互相通過系統調用kill發送軟中斷信號。內核也可以因爲內部事件而給進程發送信號,通知進程發生了某個事件。注意,信號只是用來通知某進程發生了什麼事件,並不給該進程傳遞任何數據。 

收 到信號的進程對各種信號有不同的處理方法。處理方法可以分爲三類:第一種是類似中斷的處理程序,對於需要處理的信號,進程可以指定處理函數,由該函數來處 理。第二種方法是,忽略某個信號,對該信號不做任何處理,就象未發生過一樣。第三種方法是,對該信號的處理保留系統的默認值,這種缺省操作,對大部分的信 號的缺省操作是使得進程終止。進程通過系統調用signal來指定進程對某個信號的處理行爲。 

在進程表的表項中有一個軟中斷信號域,該域中每一位對應一個信號,當有信號發送給進程時,對應位置位。由此可以看出,進程對不同的信號可以同時保留,但對於同一個信號,進程並不知道在處理之前來過多少個。




2.信號的產生


1. 用戶輸入命令,在shell下啓動一個前臺進程。

2. 用戶按下Ctrl-C,這個鍵盤輸入產生一個硬件中斷。

3. 如果CPU當前正在執行這個進程的代碼,則該進程的用戶空間代碼暫停執行,CPU從用

戶態 切換到內核態處理硬件中斷。

4. 終端驅動程序將Ctrl-C解釋成一個SIGINT信號,記在該進程的PCB中(也可以說發送了

一 個SIGINT信號給該進程)。

5. 當某個時刻要從內核返回到該進程的用戶空間代碼繼續執行之前,需先處理PCB中記

錄的信號,發現有一個SIGINT信號待處理,用這個信號的默認處理動作是終止進程,所

以直接終止進程而不再返回它的用戶空間代碼執行



3.信號處理流程

 

 

對於一個完整的信號生命週期(從信號發送到相應的處理函數執行完畢)來說,可以分爲三個階段:

1.信號誕生

2.信號在進程中註冊

3.信號的執行和註銷




阻塞信號

       實際執⾏信號的處理動作稱爲信號遞達(Delivery),信號從產⽣到遞達之間的狀態,稱爲信號未決(Pending)。進程可以選擇阻塞(Block )某個信號。被阻塞的信號產⽣時將保持在未決狀態,直到進程解除對此信號的阻塞,才 執⾏遞達的動作。 注意,阻塞和忽略是不同的只要信號被阻塞就不會遞達,⽽忽略是在遞達之後 可選的⼀種處理動作。信號在內核中的表⽰可以看作是這樣的:



block集(阻塞集、屏蔽集):一個進程所要屏蔽的信號,在對應要屏蔽的信號位置1
pending集(未決信號集):如果某個信號在進程的阻塞集中,則也在未決集中對應位置1,表示該信號不能被遞達,不會被處理
handler(信號處理函數集):表示每個信號所對應的信號處理函數,當信號不在未決集中時,將被調用



結合處理信號的三種方式:

1. SIGHUP信號未阻塞也未產⽣過,當它遞達時執⾏默認處理動作。

2. SIGINT信號產⽣過,但正在被阻塞,所以暫時不能遞達。雖然它的處理動作是忽略,但在沒 有解除阻塞之前不能忽略這個信號,因爲進程仍有機會改變處理動作之後再解除阻塞。

3. SIGQUIT信號未產⽣過,⼀旦產⽣SIGQUIT信號將被阻塞,它的處理動作是⽤戶⾃定義函數sighandler。



常規信號在遞達之前產⽣多次只計⼀次,⽽實時信號在遞達之前產⽣多次可以依次放在⼀個隊列⾥。因此,未決和阻塞標誌可以⽤相同的數據類型sigset_t來存儲,sigset_t稱爲信號集,這個類型可以表⽰每個信號的“有效”或“⽆效”狀態,在阻塞信號集中“有效”和“⽆效”的含義是該信號是否被阻塞,⽽在未決信號集中“有效”和“⽆效”的含義是該信號是否處於未決狀態。




linux信號屏蔽字



信號屏蔽字是指一個進程中當前阻塞而不能夠遞送給該進程的信號集。


信號集則是一個能表示多個信號的集合的一種數據類型,爲sigset_t。


與信號集設置相關的函數有如下幾個:


下列四個函數成功返回0,出錯返回-1
 
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);


下面函數若真返回1,若假返回0,出錯返回-1
 
int sigismember(const sigset_t *set, int signo);


sigprocmask()函數:


 
功能描述:設定對信號屏蔽集內的信號的處理方式(阻塞或不阻塞)。
用法:
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
參數:
how:用於指定信號修改的方式,可能選擇有三種:
SIG_BLOCK //加入信號到進程屏蔽。
SIG_UNBLOCK //從進程屏蔽裏將信號刪除。
SIG_SETMASK //將set的值設定爲新的進程屏蔽。
set:爲指向信號集的指針,在此專指新設的信號集,如果僅想讀取現在的屏蔽值,可將其置爲NULL。
oldset:也是指向信號集的指針,在此存放原來的信號集。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章