Linux信號簡介
時間:2017-01-05作者:華清遠(yuǎn)見
一、信號及信號來源 信號本質(zhì) 信號是在軟件層次上對中斷機(jī)制的一種模擬,在原理上,一個進(jìn)程收到一個信號與處理器收到一個中斷請求可以說是一樣的。信號是異步的,一個進(jìn)程不必通過任何操作來等待信號的到達(dá),事實(shí)上,進(jìn)程也不知道信號到底什么時候到達(dá)。 信號是進(jìn)程間通信機(jī)制中唯一的異步通信機(jī)制,可以看作是異步通知,通知接收信號的進(jìn)程有哪些事情發(fā)生了。信號機(jī)制經(jīng)過POSIX實(shí)時擴(kuò)展后,功能更加強(qiáng)大,除了基本通知功能外,還可以傳遞附加信息。 信號來源 信號事件的發(fā)生有兩個來源:硬件來源(比如我們按下了鍵盤或者其它硬件故障);軟件來源,常用發(fā)送信號的系統(tǒng)函數(shù)是kill, raise, alarm和setitimer以及sigqueue函數(shù),軟件來源還包括一些非法運(yùn)算等操作。 二、信號的種類 可以從兩個不同的分類角度對信號進(jìn)行分類:(1)可靠性方面:可靠信號與不可靠信號,(2)與時間的關(guān)系上:實(shí)時信號與非實(shí)時信號。在《Linux環(huán)境進(jìn)程間通信(一):管道及有名管道》的附1中列出了系統(tǒng)所支持的所有信號。 1、可靠信號與不可靠信號 "不可靠信號" Linux信號機(jī)制基本上是從Unix系統(tǒng)中繼承過來的。早期Unix系統(tǒng)中的信號機(jī)制比較簡單和原始,后來在實(shí)踐中暴露出一些問題,因此,把那些建立在早期機(jī)制上的信號叫做"不可靠信號",信號值小于SIGRTMIN(Red hat7.2中,SIGRTMIN=32,SIGRTMAX=63)的信號都是不可靠信號。這就是"不可靠信號"的來源。它的主要問題是: · 進(jìn)程每次處理信號后,就將對信號的響應(yīng)設(shè)置為默認(rèn)動作。在某些情況下,將導(dǎo)致對信號的錯誤處理;因此,用戶如果不希望這樣的操作,那么就要在信號處理函數(shù)結(jié)尾再一次調(diào)用signal(),重新安裝該信號。 · 信號可能丟失,后面將對此詳細(xì)闡述。 因此,早期unix下的不可靠信號主要指的是進(jìn)程可能對信號做出錯誤的反應(yīng)以及信號可能丟失。 Linux支持不可靠信號,但是對不可靠信號機(jī)制做了改進(jìn):在調(diào)用完信號處理函數(shù)后,不必重新調(diào)用該信號的安裝函數(shù)(信號安裝函數(shù)是在可靠機(jī)制上的實(shí)現(xiàn))。因此,Linux下的不可靠信號問題主要指的是信號可能丟失。 "可靠信號" 隨著時間的發(fā)展,實(shí)踐證明了有必要對信號的原始機(jī)制加以改進(jìn)和擴(kuò)充。所以,后來出現(xiàn)的各種Unix版本分別在這方面進(jìn)行了研究,力圖實(shí)現(xiàn)"可靠信號"。由于原來定義的信號已有許多應(yīng)用,不好再做改動,終只好又新增加了一些信號,并在一開始就把它們定義為可靠信號,這些信號支持排隊(duì),不會丟失。同時,信號的發(fā)送和安裝也出現(xiàn)了新版本:信號發(fā)送函數(shù)sigqueue()及信號安裝函數(shù)sigaction()。POSIX.4對可靠信號機(jī)制做了標(biāo)準(zhǔn)化。但是,POSIX只對可靠信號機(jī)制應(yīng)具有的功能以及信號機(jī)制的對外接口做了標(biāo)準(zhǔn)化,對信號機(jī)制的實(shí)現(xiàn)沒有作具體的規(guī)定。 信號值位于SIGRTMIN和SIGRTMAX之間的信號都是可靠信號,可靠信號克服了信號可能丟失的問題。Linux在支持新版本的信號安裝函數(shù)sigation()以及信號發(fā)送函數(shù)sigqueue()的同時,仍然支持早期的signal()信號安裝函數(shù),支持信號發(fā)送函數(shù)kill()。 注:不要有這樣的誤解:由sigqueue()發(fā)送、sigaction安裝的信號就是可靠的。事實(shí)上,可靠信號是指后來添加的新信號(信號值位于SIGRTMIN及SIGRTMAX之間);不可靠信號是信號值小于SIGRTMIN的信號。信號的可靠與不可靠只與信號值有關(guān),與信號的發(fā)送及安裝函數(shù)無關(guān)。目前l(fā)inux中的signal()是通過sigation()函數(shù)實(shí)現(xiàn)的,因此,即使通過signal()安裝的信號,在信號處理函數(shù)的結(jié)尾也不必再調(diào)用一次信號安裝函數(shù)。同時,由signal()安裝的實(shí)時信號支持排隊(duì),同樣不會丟失。 對于目前l(fā)inux的兩個信號安裝函數(shù):signal()及sigaction()來說,它們都不能把SIGRTMIN以前的信號變成可靠信號(都不支持排隊(duì),仍有可能丟失,仍然是不可靠信號),而且對SIGRTMIN以后的信號都支持排隊(duì)。這兩個函數(shù)的大區(qū)別在于,經(jīng)過sigaction安裝的信號都能傳遞信息給信號處理函數(shù)(對所有信號這一點(diǎn)都成立),而經(jīng)過signal安裝的信號卻不能向信號處理函數(shù)傳遞信息。對于信號發(fā)送函數(shù)來說也是一樣的。 三、信號的安裝(設(shè)置信號關(guān)聯(lián)動作) 如果進(jìn)程要處理某一信號,那么就要在進(jìn)程中安裝該信號。安裝信號主要用來確定信號值及進(jìn)程針對該信號值的動作之間的映射關(guān)系,即進(jìn)程將要處理哪個信號;該信號被傳遞給進(jìn)程時,將執(zhí)行何種操作。 linux主要有兩個函數(shù)實(shí)現(xiàn)信號的安裝:signal()、sigaction()。其中signal()在可靠信號系統(tǒng)調(diào)用的基礎(chǔ)上實(shí)現(xiàn),是庫函數(shù)。它只有兩個參數(shù),不支持信號傳遞信息,主要是用于前32種非實(shí)時信號的安裝;而sigaction()是較新的函數(shù)(由兩個系統(tǒng)調(diào)用實(shí)現(xiàn):sys_signal以及sys_rt_sigaction),有三個參數(shù),支持信號傳遞信息,主要用來與 sigqueue()系統(tǒng)調(diào)用配合使用,當(dāng)然,sigaction()同樣支持非實(shí)時信號的安裝。sigaction()優(yōu)于signal()主要體現(xiàn)在支持信號帶有參數(shù)。
1、signal() 如果該函數(shù)原型不容易理解的話,可以參考下面的分解方式來理解:
typedef void (*sighandler_t)(int); 第一個參數(shù)指定信號的值,第二個參數(shù)指定針對前面信號值的處理,可以忽略該信號(參數(shù)設(shè)為SIG_IGN);可以采用系統(tǒng)默認(rèn)方式處理信號(參數(shù)設(shè)為SIG_DFL);也可以自己實(shí)現(xiàn)處理方式(參數(shù)指定一個函數(shù)地址)。 如果signal()調(diào)用成功,返回后一次為安裝信號signum而調(diào)用signal()時的handler值;失敗則返回SIG_ERR。
2、sigaction() sigaction函數(shù)用于改變進(jìn)程接收到特定信號后的行為。該函數(shù)的第一個參數(shù)為信號的值,可以為除SIGKILL及SIGSTOP外的任何一個特定有效的信號(為這兩個信號定義自己的處理函數(shù),將導(dǎo)致信號安裝錯誤)。第二個參數(shù)是指向結(jié)構(gòu)sigaction的一個實(shí)例的指針,在結(jié)構(gòu)sigaction的實(shí)例中,指定了對特定信號的處理,可以為空,進(jìn)程會以缺省方式對信號處理;第三個參數(shù)oldact指向的對象用來保存原來對相應(yīng)信號的處理,可指定oldact為NULL。如果把第二、第三個參數(shù)都設(shè)為NULL,那么該函數(shù)可用于檢查信號的有效性。 第二個參數(shù)為重要,其中包含了對指定信號的處理、信號所傳遞的信息、信號處理函數(shù)執(zhí)行過程中應(yīng)屏蔽掉哪些函數(shù)等等。
相關(guān)資訊
發(fā)表評論
|