在產生訊號時,核心通常在程序表中設定某一種形式的標誌。當對訊號採取了這種動作時,我們說向程序遞送了乙個訊號。
在訊號產生和遞送之間的時間間隔內,稱訊號是未決的。
程序可以選用訊號遞送阻塞。如果為程序產生了乙個選擇為阻塞的訊號,而且對該程序的動作是預設動作或捕捉該訊號,則
為該程序將次訊號保持為未決狀態,直到該程序(1)對此訊號解除了阻塞,或者(2)將次訊號的動作更改為忽略。核心在
遞送乙個原來被阻塞的訊號給程序時(而不是在產生該訊號時),才決定對它的處理方式。於是子程序在訊號遞送給他之前
仍可改變對該訊號的動作。
訊號在核心中的表示可以看作是這樣的:
每個訊號都有兩個標誌位分別表示阻塞和未決,還有乙個函式指標表示處理動作。訊號產生時,核心在程序控制塊中設定該訊號
的未決標誌,直到訊號遞達才清除該標誌。在上圖的例子中,
1. sighup訊號未阻塞也未產生過,當它遞達時執行預設處理動作。
2. sigint訊號產生過,但正在被阻塞,所以暫時不能遞達。雖然它的處理動作是忽略,但在沒有解除阻塞之前不能忽略這個
訊號,因為程序仍有機會改變處理動作之後再解除阻塞。
3. sigquit訊號未產生過,一旦產生sigquit訊號將被阻塞,它的處理動作是使用者自定義函式sighandler。
如果在程序解除對某個訊號的阻塞之前,這種訊號發生了多次,那麼將如何呢?posix.1允許系統遞送該訊號一次或多次,如
果遞送多次,則稱對這些訊號進行排隊。linux是這樣實現的:常規訊號在遞達之前產生多次只計一次,而實時訊號在遞達之前
產生多次可以依次放在乙個佇列裡。
實踐:[cpp]view plain
copy
#include
#include
#include
static
void
sighandle(
intsigno)
intmain(
void
) signal(sigusr1, sighandle);
sleep(20);
if(sigprocmask(sig_unblock, &newmask, &oldmask)
while
(1)
return
0;
} 執行結果:
root@gmdz-virtual-machine:~# ./a.out &
[1] 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# kill -sigusr1 7776
root@gmdz-virtual-machine:~# receive 10
一開始sigusr1訊號被遮蔽,在sleep的時候,傳送多個sigusr1給程序,等程序甦醒後,解除sigusr1的訊號遮蔽,此時訊號
處理函式只執行了1次,也就是之前傳送的訊號只計一次。
如果在訊號處理函式執行過程中,又有訊號產生,會怎樣?
使用如下程式進行驗證:
[cpp]view plain
copy
#include
#include
static
void
sighandle(
intsigno)
intmain(
void
) if
(signal(sigusr2,sighandle))
while
(1)
return
0;
} 1.如果產生的是相同的訊號:
root@virtual-machine:~# ./a.out &
[1] 10037
root@virtual-machine:~# kill -sigusr1 10037
root@virtual-machine:~# sig 10 start
kill -sigusr1 10037
root@virtual-machine:~# kill -sigusr1 10037
root@virtual-machine:~# kill -sigusr1 10037
root@virtual-machine:~# sig 10 end
sig 10 start
sig 10 end
只有執行完當前的處理函式後才繼續執行下乙個相同訊號的處理函式,因為在執行訊號處理函式時,會將該訊號遮蔽,在執行完
處理函式後,再解除訊號的遮蔽。
2.如果產生的不是相同的訊號:
root@virtual-machine:~# ./a.out &
[1] 10140
kill -sigusr1 10140
root@gmdz-virtual-machine:~# sig 10 start
kill -sigusr2 10140 //等了7,8秒再執行該語句
sig 12 start
root@gmdz-virtual-machine:~# sig 12 end //在kill -sigusr2 10140執行了10s後出現
sig 10 end //在sig 12 end出現後立即列印出來
這邊的現象就比較奇怪了,如果產生的不是相同的訊號,能立即執行新訊號的處理函式,但是原來被打斷的訊號處理函式一直都
沒有結束,等到新的訊號處理函式結束後,舊訊號的處理函式才結束。而且是緊更著新的訊號處理函式就列印的。不明白是什麼
原因了,等以後再深入地學習後再來搞個明白吧,或者有哪位高人知道的,請告之,謝謝。
《unix環境高階程式設計》筆記2
第四章 檔案和目錄 本章將描述檔案系統特徵和檔案性質 1 stat fstat和lstat函式 原型 include int stat const char restrict pathname,struct stat restrict buf int fstat int filedes,struct...
UNIX環境高階程式設計學習筆記
include include include include int main int argc,char argv err sys can t open s argv 1 while dirp readdir dp null printf s n dirp d name closedir dp ...
unix環境高階程式設計
unix 日曆時間 自1970 年1 月1 日00 00 00 以來的國際標準時間 utc 程序時間 cpu 時間 時鐘時間 程序執行時間的總量。使用者cpu 時間 執行使用者指令時間量。系統cpu 時間 執行核心所經歷時間。命令 time 第三章至第七章 原子操作 任何乙個要求多於1 個函式呼叫的...