理解訊號遞達和阻塞的概念和原理
首先我們看一下什麼是阻塞訊號?
阻塞訊號
1、訊號其他相關概念
實際執行訊號的處理動作稱為訊號遞達(delivery)
訊號遞達有三種方式:
1、忽略
2、預設動作
3、自定義捕捉
訊號從產生到遞達之間的狀態,稱為訊號未決(pending)。
程序可以選擇阻塞 (block )某個訊號。
被阻塞的訊號產生時將保持在未決狀態,直到程序解除對此訊號的阻塞,才執行遞達的動作。
注意:阻塞和忽略是不同的,只要訊號被阻塞就不會遞達,而忽略是在遞達之後可選的⼀種處理動作。
總結:2、在核心中的表示
訊號在核心中的表示示意圖
每個訊號都有兩個標誌位分別表示阻塞(block)和未決(pending),還有乙個函式指標表示處理動作。訊號產生時,核心在程序控制塊中設定該訊號的未決標誌,直到訊號遞達才清除該標誌。在上圖的例子中,sighup訊號未阻塞也未產生過,當它遞達時執行預設處理動作。 sigint訊號產生過,但正在被阻塞,所以暫時不能遞達,雖然它的處理動作是忽略,但在沒有解除阻塞之前不能忽略這個訊號,因為程序仍然有機會改變處理動作之後再解除阻塞。 sigquit訊號未產生過,⼀旦產生sigquit訊號將被阻塞,它的處理動作是使用者自定義函式sighandler。 如果在程序解除對某訊號的阻塞之前這種訊號產生過多次,將如何處理?posix.1允許系統遞送該訊號一次或多次。linux是這樣實現的:常規訊號在遞達之前產生多次只計一次,而實時訊號在遞達之前產生多次可以依次放在乙個佇列裡。我們現在不討論實時訊號。
3.sigset_t
從上圖來看,每個訊號只有乙個bit的未決標誌,非0即1,不記錄該訊號產生了多少次,阻塞標誌也是這樣表示的。 因此,未決和阻塞標誌可以用相同的資料型別sigset_t來儲存,sigset_t稱為訊號集,這個型別可以表示每個訊號的「有效」或「無效」狀態,在阻塞訊號集中「有效」和「無效」的含義是該訊號是否被阻塞,而在未決訊號集中「有效」和「無效」的含義是該訊號是否處於未決狀態。
阻塞訊號集也叫做當前程序的
訊號遮蔽字(signal mask),
這裡的「遮蔽」應該理解為阻塞而不是忽略。
4.訊號集操作函式
sigset_t型別對於每種訊號用乙個bit表示「有效」或「無效」狀態,至於這個型別內部如何儲存這些bit則依賴於系統實現,從使用者的角度是不必關心的,使用者只能呼叫以下函式來操作sigset_t變數,而不應該對它的內部資料做任何解釋,比如用printf直接列印sigset_t變數是沒有意義的。
#include int sigemptyset(sigset_t *set); //初始化set所指向的訊號集,使所有訊號的對應位清0
int sigfillset(sigset_t *set); //初始化set所指向的訊號集,表示該訊號集的有效訊號包括系統支援的所有訊號
int sigaddset(sigset_t *set, int signo); //在該訊號集中新增有效訊號
int sigdelset(sigset_t *set, int signo); //在該訊號集中刪除有效訊號
int sigismember(const sigset_t *set, int signo); //用於判斷乙個訊號集的有效訊號中是否包含某種訊號結構體的引數表示訊號集,訊號操作的時候都是以訊號集合的方式進行操作,需要事先建立乙個該結構體的物件,然後把想要操作的訊號新增到訊號集合物件當中去
1、sigset_t結構體的引數表示訊號集,訊號操作的時候都是以訊號集合的方式進行操作,需要事先建立乙個該結構體的物件,
然後把想要操作的訊號新增到訊號集合物件當中去。
2、函式sigemptyset初始化set所指向的訊號集,使其中所有訊號的對應bit清零,表示該訊號集不包含任何有效訊號。
3、函式sigfillset初始化set所指向的訊號集,使其中所有訊號的對應bit置位,表示該訊號集的有效訊號包括系統支援的所有訊號。
注意:在使用sigset_ t型別的變數之前,一定要呼叫sigemptyset或sigfillset做初始化,使訊號集處於確定的狀態。初始化sigset_t變數之後就可以在呼叫sigaddset和sigdelset在該訊號集中新增或刪除某種有效訊號。
這四個函式都是成功返回0,出錯返回-1。sigismember是乙個布林函式,用於判斷乙個訊號集的有效訊號中是否包含某種訊號,若包含則返回1,不包含則返回0,出錯返回-1。
sigprocmask
乙個程序的訊號遮蔽字規定了當前阻塞而不能遞送給該程序的訊號集。呼叫函式sigprocmask可以檢測或更改(或兩者)程序的訊號遮蔽字。如果呼叫sigprocmask解除了對當前若干個未決訊號的阻塞,則在sigprocmask返回前,至少將其中 乙個訊號遞達。
引數解析:
how,有三個巨集
sig_blockset包含了我們希望新增到當前遮蔽字的訊號,相當於mask=mask|set
sig_unblock
set包含了我們希望從當前訊號遮蔽字中解除阻塞的訊號,相當於mask=mask&~set
sig_setmask
設定當前遮蔽字為set所指向的值,相當於mask=set
set表示新設定的訊號遮蔽字,oset表示當前訊號遮蔽字
處理方式:
set非空,oset為null :按照how指示的方法更改set指向訊號集的訊號遮蔽字。
set為null,oset非空:讀取oset指向訊號集的訊號遮蔽字,通過oset引數傳出。
set和oset都非空 :現將原來的訊號遮蔽字備份到oset裡,然後根據set和how引數更改訊號遮蔽字。
如果呼叫segprocmask解除了對於當前若干個未決訊號的阻塞,則在sigprocmask返回前,至少將其中乙個訊號遞達。
sigpending
#includesigpending
//讀取當前程序的未決訊號集,通過set引數傳出。呼叫成功後則返回0;失敗則返回-1。
下面用咱們用剛學習的幾個函式完成乙個小的實驗。程式如下:
#include #include#includevoid printset(const sigset_t *set)
else
} printf("\n");
}
int main(int argc, char *argv)
while(1)
printset(&pset);//列印未決訊號集
程式執行時,每秒鐘把個各訊號的未決狀態列印一遍,由於我們阻塞了sigint訊號,按ctrl + c將會使訊號處於未決狀態,按ctrl-\仍然可以終止程式,因為sigquit 訊號沒有被阻塞。
Linux Linux程序訊號2
我們在 linux程序訊號1中學習了什麼是程序訊號,訊號如何產生等,今天我們繼續學習一些關於程序訊號相關的知識 訊號相關的其他常見概念 訊號在核心中的表示 訊號集操作函式我們前面一直提訊號的捕捉或者遞達這一概念,那麼在作業系統中到底是什麼時候進行訊號的捕捉呢?我們依舊使用一張圖來表達我們的流程 核心...
Linux程序間通訊 2 訊號
unix網路程式設計 卷2 程序間通訊 第2版 中文版 訊號本質 訊號是在軟體層次上對中斷機制的一種模擬。在原理上,乙個程序收到乙個訊號與處理器收到乙個中斷請求可以說是一樣的。訊號是非同步的,乙個程序不必通過任何操作來等待訊號的到達,事實上,程序也不知道訊號到底什麼時候到達。訊號可以直接進行使用者空...
Linux程序訊號 訊號處理
一 訊號相關概念 1.實際執行訊號的處理動作稱為訊號遞達 delivery 2.訊號從產生到遞達之間的狀態稱為訊號未決 pending 不一定會立即delivery 3.程序可以選擇阻塞 block 某個訊號。不會遞達 4.被阻塞的訊號產生時將保持在未決狀態,知道程序解除對此訊號 的阻塞,才會執行遞...