在linux的程序中可以接收到各種的訊號,並且如果你不對訊號進行處理,linux中的程序就會採用預設的處理方式處理,比如ctrl-c的訊號,程序對它的處理就是終止程序的執行。
在linux中,我們也可以在程序中遮蔽掉某些訊號,使程序不去處理這些訊號,但其中的sigkill和sigstop是不能被阻塞的。
在這裡先介紹幾個訊號的函式:
int sigempty(sigset_t *set); // 清空訊號集set
int sigfillset(sigset_t *set); // 填滿訊號集,即讓set包含所有的訊號
int sigaddset(sigset_t *set, int signo); // 在set中增加signo訊號
int sigdelset(sigset_t *set, int signo); // 在set中去掉signo訊號
int sigismember(sigset_t *set, int signo); // 訊號signo是否在訊號集set中
int sigprocmask(int how, const sigset_t set, sigset_t oset); // 若oset非空,則程序的當前訊號遮蔽字通過oset返回,若set是乙個非空指標,著引數how指示如何修改當前訊號的遮蔽字,how可以取三個值:
sig_block:增加乙個訊號。
sig_unblock:解除乙個訊號。
sig_setmask:該程序的訊號將被set訊號集取代。
int sigpengding(sigset_t *set); // 該函式返回訊號集,該訊號通過set引數返回。
以上函式都在#include 標頭檔案中。
下面用《unix環境高階程式設計》裡的乙個例子說明一下,**有所修改,先看**(main.c,裡面有個人對**的注釋):
view plain
copy to clipboard
print?
#include
#include
#include
static
void
sig_quit(int);
intmain(void)
//設定乙個空的訊號集
sigemptyset(&newmask);
sigaddset(&newmask, sigquit); // 在這個訊號集中增加sigquit訊號
//在當前程序中增加newmask訊號集作為遮蔽訊號集,oldmask返回當前程序的訊號集
if (sigprocmask(sig_block, &newmask, &oldmask) < 0)
sleep(5);
//返回當前程序訊號集
if (sigpending(&pendingmask) < 0)
//檢查sigquit訊號是否在當前訊號集中
if (sigismember(&pendingmask, sigquit))
printf("/nsigquit pending/n");
//恢復程序的訊號集
if (sigprocmask(sig_setmask, &oldmask, null) < 0)
printf("sigquit unblocked/n");
sleep(5);
exit(0);
} static
void
sig_quit(int signo)
} 編譯: gcc main.c
生成:a.out
執行:./a.out
輸出如下(ubuntu9.10):
^/
sigquit pending
caught sigquit
sigquit unblocked
^/退出
下面解釋一下輸出:
^/ 在第一次sleep(5)的5秒中內產生訊號一次(按ctrl+/)
sigquit pending 從sleep返回後
caught sigquit 在訊號處理函式中
sigquit unblocked 從sigprocmask返回後
^/退出 再次產生訊號
我們對著程式來看下輸出。
在我們設定sigquit遮蔽字和恢復程序的訊號集這段時間,我們產生的sigquit訊號,我們的程序並沒去處理,所以輸出了sigquit pending 。
在我們恢復程序的訊號集後,我們程序就撲捉到了我們剛才產生的訊號,因而就輸出了caught sigquit,在sig_quit函式中,我們恢復了sigquit的預設處理方式(即終止程序執行),程序當我們再次產生sigquit訊號,程序就退出了。
當我們產生程序時,一些unix系統會對程序中要處理的訊號進行排隊,我們的程序會對訊號佇列中的訊號進行處理。我們再執行一下剛才的程式,在第一次sleep(5)的5秒中內產生訊號10次訊號,看下會怎麼樣,下面是我的輸出:
^/^/^/^/^/^/^/^/^/^/
sigquit pending
caught sigquit
sigquit unblocked
^/退出
下面解釋一下輸出:
^/^/^/^/^/^/^/^/^/^/ 在第一次sleep(5)的5秒中內產生訊號10次訊號
sigquit pending 從sleep返回後
caught sigquit 從sigprocmask返回後
sigquit unblocked 從sigprocmask返回後
^/退出 再次產生訊號
這裡可以看到linux系統對沒有對訊號進行排隊,產生10次訊號,只處理一次。
在上面的例子中,我們用signal函式來指定訊號的處理函式,用sigprocmask來指定訊號遮蔽字,其實這些都可以在乙個函式中解決,它就是sigaction,推薦使用sigaction函式。
linux 訊號集操作
訊號掩碼 被阻塞的訊號集 每個程序都有乙個用來描述哪些訊號傳送來將被阻塞的訊號集,如果某種訊號在某個程序的阻塞訊號集中,則傳送到該程序的此種訊號將會被阻塞。當前被程序阻塞的訊號集也叫訊號掩碼,型別為sigset t。每個程序都有自己的訊號掩碼,且建立子程序時,子程序會繼承父程序的訊號掩碼。訊號阻塞和...
Linux 訊號的處理以及訊號集操作函式
首先來再次看看這張圖 從上圖來看,每個訊號只有乙個bit的未決標誌,非0即1,不記錄該訊號產生了多少次,阻塞標誌也是這樣表示的。因此,未決和阻塞標誌可以用相同的資料型別sigset t來儲存,sigset t稱為訊號集,這個型別可以表示每個訊號的 有效 或 無效 狀態,在阻塞訊號集中 有效 和 無效...
訊號(六)訊號集操作函式
一 核心通過讀取未決訊號集來判斷訊號是否應該被處理。訊號遮蔽字mask可以影響未決訊號集。為我們可以在應用程式中自定義set來改變mask,來達到遮蔽指定訊號的目的。二 訊號集設定 sigset t set typedef unsigned long sigset t int sigemptyset...