四、訊號遮蔽字:
有時候我們希望程序正確的執行,而不想程序受到訊號的影響,比如我們希望上面那個程式在
1秒鐘之後不結束。這個時候我們就要進行訊號的操作了。
訊號操作最常用的方法是訊號遮蔽。訊號遮蔽要用到下面的幾個函式。
sigemptyset
,sigfillset
,sigaddset
,sigdelset
,sigismember
,sigprocmask
。下面對他們分別進行講解。8.
名稱::sigemptyset/sigfillset/sigaddset/sigdelset/sigismember功能:
處理訊號集
標頭檔案:
#include
函式原形:
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signum);
int sigdelset(sigset_t *set,int signum);
int sigismember(const sigset_t *set,int signum);
引數:set
訊號集signum
訊號返回值:
若成功返回
0,若出錯返回-1。
若真返回
1,若假返回
0,若出錯返回-1。
sigismember
我們需要有乙個能表示多個訊號—訊號集的資料型別。我們將在諸如
sigprocmask
之類的函式中使用這種資料型別,以便告訴核心不允許發生該訊號集中的訊號。上面的
5個函式可以對訊號集進行處理。
函式sigemptyset
初始化由
set指向的訊號集,清除其中所有訊號。函式
sigfillset
初始化由
set指向的訊號集,使其包含所有訊號。所以訊號在使用訊號集前,要對訊號集呼叫
sigemptyset
或sigfillset
一次。函式
sigaddset
將乙個訊號新增到現有集中,
sigdelset
則從訊號集中刪除乙個訊號。對所有以訊號集作為引數的函式,我們總是以訊號集位址作為其傳送的引數。
sigismember
查詢訊號是否在訊號集合之中。
下面的例子:
/*10_7.c*/
#include
#include
main()
下面是執行結果:
# ./10_7
sigusr1
sigint
程式先初始化訊號集,清除其中所有訊號,然後把
sigusr1
和sigint
新增到訊號集中,然後測試
sigusr1
,sigusr2
,sigint
訊號是否在訊號集中。因為
sigusr2
不在訊號集中,所以程式並不列印
sigusr2。9
.名稱::
sigprocmask功能:
檢測或更改訊號遮蔽字
標頭檔案:
#include
函式原形
:int sigprocmask(int how,const sigsett_t *set,sigset_t *oldset);
引數:how
操作方式
set訊號集
oldest
返回值:
若成功返回
0,若出錯返回-1。
每個程序都有乙個用來描述哪些訊號遞送到程序時將被阻塞的訊號集,該訊號集中的所有訊號在遞送到程序後都將被阻塞。
sigprocmask
是最為關鍵的乙個函式。在使用之前要先設定好訊號集合
set。這個函式的作用是將指定的訊號集合
set加入到程序的訊號阻塞集合之中去,如果提供了
oldset
那麼當前的程序訊號阻塞集合將會儲存在
oldset
裡面。引數
how決定函式的操作方式。
sig_block
:增加乙個訊號集合到當前程序的阻塞集合之中。
sig_unblock
:從當前的阻塞集合之中刪除乙個訊號集合。
sig_setmask
:將當前的訊號集合設定為訊號阻塞集合。
我們把10_7.c
稍微修改一下,看看
sigprocmask
函式的功能。
/*10_8.c*/
#include
#include
main()
程式先定義訊號集
set,然後把訊號
sigint
新增到set
訊號集中,最後把
set設定為訊號阻塞集合。當我們執行程式時,程序進入死迴圈。我們按「
ctrl+c」
系統並沒有中斷程式,因為我們已經把
sigint
訊號遮蔽掉了。我們可以按
」ctrl+z」
來結束程式。
sigeprocmask
函式通常和
sigemptyset/sigfillset/sigaddset/sigdelset/sigismember
函式配合使用,主要有兩種用途:
1.我們不希望某些不太重要的訊號來影響我們的程序,我們就可以把這些訊號新增到訊號遮蔽集中。使它們不打擾程序的執行。
2.如果系統現在很忙,沒有時間及時相應訊號,程序可以先把訊號阻塞掉,等系統有空閒時間在去相應,這也保證了訊號的可靠性。下面的函式可以做到這一點。10.
名稱::sigpending
功能:返回訊號集
標頭檔案:
#include
函式原形:
int sigpending(sigset_t *set);
引數:返回值:
若成功返回
0,若出錯返回-1。
我們要注意的是,阻塞訊號並不是丟棄訊號,它們被儲存在乙個程序的訊號阻塞佇列裡,
sigpending
可以獲得當前已遞送到程序,卻被阻塞的所有訊號,在
set指向的訊號集中返回這些訊號。
下面是乙個例子:
/*10_9.c*/
#include
#include
#include
int main(void)
程式開始執行,如果我們在
5秒鐘內按
」ctrl+c」,sigint
訊號會被傳遞到程序,但是由於程序設定了訊號阻塞集,訊號
sigint
在這個集合中,所有這個訊號被阻塞。並由
sigpend
儲存到程序的訊號阻塞佇列
pendmask裡.
然後我們用
sigismember
檢測sigint
是否在訊號阻塞佇列
pendmask
裡。文章**:http://blog.chinaunix.net/u1/59291/showart.php?id=538597
unix 環境高階程式設計 讀書筆記
unix環境高階程式設計 讀書筆記 第8章exit和 exit區別 exit會直接進入核心,不會關閉io流。程序基本控制函式還有 wait,fork,exec。atexit 程式正常退出時呼叫,如果因為signal退出則不能呼叫。功能 註冊函式可以完成一些清理工作,比如全域性log類,可以不設定析構...
unix環境高階程式設計 讀書筆記
檔案 unix支援在不同程序之間共享開啟的檔案。核心使用三種資料結構表示開啟的檔案 原子操作 一般而言,原子操作指的是由多步組成的操作。如果該操作原子的執行,要麼執行完所有步,要麼一步也不執行,不可能只執行所有步驟的乙個子集。2 注意 原子操作函式 pread,pwrite pread 相當於呼叫r...
Unix環境高階程式設計 讀書筆記一
unix 基礎知識 這一章主要是unix系統的概論以及一些概念的介紹,主要分為10個小節 1 登陸 2 檔案和目錄 3 輸入和輸出 4 程式和程序 5 ansi c 6 出錯處理 7 使用者標識 8 訊號 9 unix時間值 10 系統呼叫和庫函式 這個都比較簡單,就不再重複敘述了。在標頭檔案中定義...