一、信號集操作函數
內核通過讀取未決信號集來判斷信號是否應被處理。信號屏蔽字mask可以影響未決信號集。而我們可以在用程序自定義set來改變mask,來達到屏蔽指定信號目的。
sigset_t set; // typedef unsigned long sigset_t
int sigemptyset(sigset_t *set) // 將某個信號集清0
int sigfillset(sigset_t *set) // 將某個信號集置1
int sigaddsetset(sigset_t *set, int sino) // 將某個信號加入信號集
int sigdelset(sigset_t *set, int signo) // 將某個信號清出信號集
int sigismember(cosnt sigset_t *set, int signum); // 判斷某個信號是否在信號集中
?
二、函數sigprocmask
1. 函數原型:用來屏蔽信號、解除信號屏蔽使用該函數,其本質,讀取或修改進程的信號屏蔽字(PCB)
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
分析:
- set:傳入參數,是一個位圖,set中哪個位置置為1,就表示當前進程屏蔽了哪個信號
- oldset:傳出參數,保存舊的信號屏蔽集
- how參數取值
how | 說明 |
---|---|
SIG_BLOCK | 當how設置為此值,set表示需要屏蔽的信號 |
SIGB_UNBLOCK | 當how設置為此值,set表示需要解除屏蔽的信號 |
SIG_SETMASK | 當how設置為此值,set表示用于替代原始屏蔽集的新屏蔽集,相當于mask = set,若調用sigprocmask解除了對當前信號若干個信號的阻塞,則在sigprocmask返回前,至少將其中一個信號遞達。 |
嚴格注意,屏蔽信號:只是將信號處理延后執行(延至解除屏蔽);而忽略表示將信號丟處理
?
三、函數sigpending
? ? ?函數作用:讀取當前信號的未決信號集
int sigpending(sigset_t *set); //set傳出參數
?
四、程序清單
1. 測試代碼
#include <stdio.h>
#include <signal.h>
#include <unistd.h>void printped(sigset_t *ped)
{int i;for (i = 1; i < 32; i++) {if (sigismember(ped, i) == 1) putchar('1');else putchar('0');}printf("\n");
}int main()
{sigset_t myset, oldset, ped;sigemptyset(&myset);sigaddset(&myset, SIGQUIT); // Ctrl + /sigaddset(&myset, SIGINT); // Ctrl + Csigaddset(&myset, SIGTSTP); // Ctrl + Zsigaddset(&myset, SIGSEGV);sigaddset(&myset, SIGKILL); //無法被屏蔽sigprocmask(SIG_BLOCK, &myset, &oldset);while (1) {sigpending(&ped);printped(&ped);sleep(2);}return 0;
}
輸出結果:
?
?
2. 測試代碼
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>void handler(int sig);void printsigset(sigset_t *set)
{int i;for (i = 1; i < 32; ++i) {if (sigismember(set, i))putchar('1');elseputchar('0');}printf("\n");
}int main(int argc, char *argv[])
{sigset_t pset;sigset_t bset;sigemptyset(&bset);sigaddset(&bset, SIGINT);if (signal(SIGINT, handler) == SIG_ERR) {perror("signal error");exit(1);}if (signal(SIGQUIT, handler) == SIG_ERR) {perror("signal error");exit(1);}sigprocmask(SIG_BLOCK, &bset, NULL);for (; ;) {sigpending(&pset);printsigset(&pset);sleep(1);}return 0;
}void handler(int sig)
{if (sig == SIGINT)printf("recv a sig = %d\n", sig);else if (sig == SIGQUIT) {sigset_t uset;sigemptyset(&uset);sigaddset(&uset, SIGINT);sigprocmask(SIG_UNBLOCK, &uset, NULL);}
}
輸出結果: