Linux 訊號阻塞與遮蔽

2022-05-19 13:50:46 字數 2842 閱讀 1029

1. sigprocmask函式提供遮蔽和解除遮蔽訊號的功能。 

從而實現關鍵**的執行不被打斷。 

函式宣告如下:

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

其中引數 how可設定的引數為:sig_block, sig_unblock,sig_setmask 

sig_block: 

按照引數 set 提供的遮蔽字,遮蔽訊號。並將原訊號遮蔽儲存到oldset中。 

sig_unblock: 

按照引數 set 提供的遮蔽字進行訊號的解除遮蔽。針對set中的訊號進行解屏。 

sig_setmask: 

按照引數 set 提供的訊號設定重新設定系統訊號設定。

2. 訊號遮蔽與解屏常見實現 

方法一: sig_block, sig_unblock成對實現 

優點oldset可以不管。

方法二: 

sig_block設定遮蔽,儲存原有訊號設定。 

sig_setmask重新恢復原有設定。

3. 遮蔽過程中接受到的訊號如何處理 

在訊號遮蔽過程中,出現的所有被遮蔽的訊號,不管發生多少次,在訊號解除遮蔽後,系統會執行一次被遮蔽訊號上的操作。

#include#include#includeint flag_sigusr1 = 0;

int flag_sigusr2 = 0;

void sig_usr1(int signo)

void sig_usr2(int signo)

int main(void)

sleep(5);

}fprintf(stdout, "first while was broken\n");

//重新設定為0

flag_sigusr1 = 0;

flag_sigusr2 = 0;

// block sigusr1

sigemptyset(&newmask);

sigaddset(&newmask, sigusr1);

if(sigprocmask(sig_block, &newmask, &oldmask) < 0)

fprintf(stdout, "only catch sigusr2 can break, because sigusr1 has been blocked\n");

while(1)

sleep(5);

}fprintf(stdout, "second while was broken\n");

fprintf(stdout, "after second while was broken, flag_sigusr1=%d, flag_sigusr2=%d\n", flag_sigusr1, flag_sigusr2);

return 0;

}

多執行緒情況下每個執行緒共用訊號處理函式,但是每個執行緒可以選擇自己是否block某個訊號。

再看乙個多執行緒的例子:子執行緒的功能同上,主線程接收到hup訊號會向子執行緒傳送usr2訊號。

#include#include#include#includeint flag_sigusr1 = 0;

int flag_sigusr2 = 0;

int flag_sighup = 0;

void sig_usr1(int signo)

void sig_usr2(int signo)

void sig_hup(int signo)

void *thread_control_signal(void *arg)

fprintf(stdout, "thread|first while. catch sigusr1 or sigusr2 can break\n");

while(1)

sleep(5);

}flag_sigusr1 = 0;

//thread block sigusr1

sigaddset(&newmask, sigusr1);

if(pthread_sigmask(sig_block, &newmask, &oldmask) < 0)

fprintf(stdout, "thread|first while. catch sigusr2 can break\n");

while(1)

sleep(10);

}fprintf(stdout, "thread|thread exit\n");

return (void *)0;

}int main()

//main thread block sigusr1

sigemptyset(&newmask);

sigaddset(&newmask, sigusr1);

if(pthread_sigmask(sig_block, &newmask, null) < 0)

//main thread wait sighup

sigemptyset(&newmask);

sigaddset(&newmask, sighup);

if(sigwait(&newmask, &signo) < 0)

fprintf(stdout, "main|get sighup\n");

pthread_kill(tid, sigusr2);

pthread_kill(tid, sigusr2);

pthread_join(tid, null);

fprintf(stdout, "main|exit\n");

return 0;

}

kill函式向程序傳送訊號,pthread_kill用於向執行緒傳送訊號。

阻塞訊號及訊號遮蔽pending

1.訊號在核心中的三種表示 1 訊號遞達 實際執行訊號的處理動作 2 訊號未決 pending 訊號從產生到遞達的狀態,是一種記錄狀態 3 阻塞訊號 block 被阻塞的訊號不會遞達,它在產生時處於未決狀態,直到程序解除對這個訊號的阻塞,才會執行遞達,但不會立即遞達 阻塞與忽略的不同 忽略是在訊號遞...

linux訊號集與訊號遮蔽字

訊號傳遞過程 一些名詞 需要注意的是 這些變數之間也存在一些關係,比如 程序將訊號遮蔽字的2號為置為1,也就是說遮蔽sigint訊號,那麼但你向程序傳送該訊號時 ctrl c 該訊號必然處於未決狀態。那麼,訊號未決狀態字的2號位自然也就是1啦。訊號集操作函式 posix.1 定義了乙個資料型別sig...

linux 訊號遮蔽

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