linux程序中的訊號遮蔽

2021-05-21 20:19:46 字數 4035 閱讀 4169

在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 plaincopy to clipboardprint?

#include

#include

#include

static void sig_quit(int);  

int   

main(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)  

}  #include

#include

#include

static void sig_quit(int);

int

main(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函式。

pthread_sigmask與sigprocmask。前者是執行緒安全的。

pthread_sigmask改變的是執行緒的訊號集與整個程序無關。

Linux中如何遮蔽訊號

本篇文章主要學習linux的訊號處理機制,著重學習遮蔽訊號部分。遮蔽訊號處理的兩種方式類似於訊號的捕獲,一種方式是直接對其設定,另一種方式是先獲得描述符的掩碼,然後對其設定操作。本文主要參考自 嵌入式linux系統使用開發 作者何永琪,thanks.在linux系統中,如何處理某個程序傳送的乙個特定...

linux 訊號遮蔽

include include include include include include sigemptyset newmask 獲取空遮蔽訊號集 sigfillset newmask 獲取遮蔽了所有訊號的遮蔽訊號集,除了那兩個sigkill sigstop sigpending pendma...

Linux中的程序訊號

訊號概念訊號 系統為了響應某些狀況而產生的事件,程序收到訊號需要採取相應的動作。訊號產生訊號產生的條件 1 按下終端鍵 ctrl c ctrl 2 硬體異常 除零操作 無效記憶體 3 某些軟條件發生 時間片到 4 管道破裂 用kill l 可以檢視系統定義的訊號列表 訊號產生的方式 1 通過終端鍵產...