linux訊號的阻塞和未決
執行訊號的處理動作稱為訊號遞達(Delivery),訊號從產生到遞達之間的狀態,稱為訊號未決(Pending)。
程式可以選擇阻塞(Block)某個訊號。被阻塞的訊號產生時將保持在未決狀態,直到程式解除對此訊號的阻塞,才執行遞達的動作。注意,阻塞和忽略是不同,只要訊號被阻塞就不會遞達,而忽略是在遞達之後可選的一種處理動作。
訊號在核心中的表示可以看作是這樣的:
1:PCB程式控制塊中函式有訊號遮蔽狀態字(block)訊號未決狀態字(pending)還有是否忽略標誌(或是訊號處理函式);block狀態字、pending狀態字 64bit;
2:訊號遮蔽狀態字(block),1代表阻塞、0代表不阻塞;訊號未決狀態字(pending)的1代表未決,0代表訊號可以抵達了;它們都是每一個bit代表一個訊號,比如,bit0代表訊號SIGHUP;
3:比如向程式傳送SIGINT,核心首先判斷訊號遮蔽狀態字是否阻塞,如果該訊號被設為為了阻塞的,那麼訊號未決狀態字(pending)相應位製成1;若該訊號阻塞解除,訊號未決狀態字(pending)相應位製成0;表示訊號此時可以抵達了,也就是可以接收該訊號了。
4:遮蔽狀態字使用者可以讀寫,未決狀態字使用者只能讀;這是訊號設計機制。
API函式:
訊號集操作函式,對狀態字進行操作(遮蔽狀態字和未決狀態字):
#include <signal.h>
int sigemptyset(sigset_t *set);//將訊號集清空,共64bits
int sigfillset(sigset_t *set);//將訊號集置1
int sigaddset(sigset_t *set, int signum);//將signum對應的位置為1
int sigdelset(sigset_t *set, int signum);//將signum對應的位置為0
int sigismember(const sigset_t *set, int signum);//判斷signum是否在該訊號集合中,如果集合中該位為1,則返回1,表示位於在集合中
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
引數how有下面三種取值:SIG_BLOCK: 將引數set指向的訊號集中設定的訊號新增到現在的遮蔽狀態字中,設定為阻塞;
SIG_UNBLOCK:將引數set指向的訊號集中設定的訊號新增到現在的遮蔽狀態字中,設定為非阻塞, 也就是解除阻塞;
SIG_SETMASK:將引數set指向的訊號集直接覆蓋現在的遮蔽狀態字的值;
如果oset是非空指標,則讀取程式的當前訊號遮蔽字通過oset引數傳出。
若成功則為0,若出錯則為-1
還有一個函式可以讀取未決狀態字(pending)資訊
#include <signal.h>
int sigpending(sigset_t *set);
例項:
SIGINT訊號設定阻塞,檢視未決關鍵字傳送SIGINT訊號,檢視未決關鍵字
傳送SIGQUIT訊號解除SIGINT訊號阻塞,檢視未決關鍵字
剛開始設定SIGINT訊號為阻塞訊號,當按下Ctrl+c傳送中斷訊號SIGINT(值為2,所以後來第二位被置1)之前,未決狀態字的所有位都是0,因為此時沒有未抵達的訊號;
當傳送SIGINT訊號後,因為該訊號是阻塞的,所以未決狀態字將第二位置為了1,表示該訊號在這裡阻塞了;當我按下Ctrl+\傳送SIGQUIT訊號後,又將SIGINT訊號設定為了非阻塞的;此時可以看到未決狀態字的所有位都變為了0;並且也收到了剛才阻塞的SIGINT訊號;
/*************************************************************************
> File Name: block_pending.cpp
> Author:
> Mail:
> Created Time: 2015年12月17日 星期四 17時13分45秒
************************************************************************/
#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
void handler(int num)
{
if(num == SIGINT){
cout << "剛才收到了訊號SIGQUIT, 取消了阻塞,收到中斷訊號.." << endl;
}
else if (num == SIGQUIT){
//將SIGINT訊號設定為非阻塞的
sigset_t un_bset;
sigemptyset(&un_bset);
sigaddset(&un_bset, SIGINT);
sigprocmask(SIG_UNBLOCK, &un_bset, NULL);
}
}
void print_pending(sigset_t * pset)
{
int i = 0;
cout << "未決狀態字(64位):";
for (i = 1; i <= 64; ++i){
if(sigismember(pset, i))
cout << 1;
else
cout << 0;
if(i % 8 == 0){
cout << " ";
}
}
cout << endl;
}
int main()
{
sigset_t bset;
sigset_t pset;
//設定SIGINT訊號
sigemptyset(&bset);
sigaddset(&bset, SIGINT);
signal(SIGINT, handler);
signal(SIGQUIT, handler);
//將SIGINT訊號設定為阻塞的
sigprocmask(SIG_BLOCK, &bset, NULL);
while(1){
//得到未決狀態字
sigpending(&pset);
//顯示未決狀態字
print_pending(&pset);
sleep(1);
}
exit(0);
}
相關文章
- linux系統程式設計之訊號(五):訊號集操作函式,訊號阻塞與未決Linux程式設計函式
- Linux 未決訊號集與訊號遮蔽字Linux
- Linux--訊號阻塞與遮蔽Linux
- linux中的兩個非常重要的訊號:SIGALRM訊號和SIGCHID訊號LinuxGC
- 從linux原始碼看socket的阻塞和非阻塞Linux原始碼
- 從 Linux 原始碼看 socket 的阻塞和非阻塞Linux原始碼
- Linux 下的程式間通訊:套接字和訊號Linux
- Linux 阻塞和非阻塞 IO 實驗學習Linux
- Linux裝置驅動中的阻塞和非阻塞I/OLinux
- Linux訊號機制與訊號處理Linux
- Linux下訊號燈的使用Linux
- SIGALRM訊號和SIGCHID訊號GC
- 深入淺出:Linux裝置驅動中的阻塞和非阻塞I/OLinux
- linux中條件變數和訊號量的區別!Linux變數
- Linux的SIGUSR1和SIGUSR2訊號Linux
- linux 訊號機制Linux
- Linux 訊號量大全Linux
- linux訊號表(轉)Linux
- 蛻變成蝶:Linux裝置驅動中的阻塞和非阻塞I/OLinux
- Linux中訊號量的實現Linux
- Linux中的System V訊號量Linux
- linux 下的訊號量引數Linux
- linux 訊號與處理Linux
- Linux訊號簡介(轉)Linux
- Linux程式間通訊——使用訊號量Linux
- linux程式間通訊-----訊號總結Linux
- 同步和非同步關注的是訊息通訊機制,阻塞和非阻塞關注的是程式在等待呼叫結果(訊息,返回值)時的狀態非同步
- 【死磕NIO】— 阻塞IO,非阻塞IO,IO複用,訊號驅動IO,非同步IO,這你真的分的清楚嗎?非同步
- linux中的訊號處理與SROPLinux
- Linux Shell的訊號trap功能細節Linux
- Linux的kill命令與訊號控制(轉)Linux
- 同步、非同步、阻塞和非阻塞非同步
- 【linux】系統程式設計-1-程式、管道和訊號Linux程式設計
- Linux訊號捕捉之sigactionLinux
- Linux SIGCHLD訊號處理LinuxGC
- Linux訊號處理機制Linux
- Linux訊號(signal)機制Linux
- linux系統程式設計之訊號(一):中斷與訊號Linux程式設計