| 操作 | 行為 | 信號狀態 |
|---|---|---|
| 阻塞 | 暫時延遲遞送 | 待決,解除阻塞後遞送 |
| 忽略 | 直接丟棄 | 不再遞送,也不排隊 |
阻塞是「暫緩」,忽略是「拒收」。阻塞期間信號會排隊(最多一個,除非使用即時信號)。
#include <signal.h>
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oldset);
how 取值:
SIG_BLOCK // 新屏蔽集 = 當前 ∪ set
SIG_UNBLOCK // 新屏蔽集 = 當前 \ set
SIG_SETMASK // 新屏蔽集 = set
set : 新增/移除的信號集指標(NULL 表示不修改,僅查詢)
oldset : 儲存舊屏蔽集指標(NULL 表示不需儲存)
回傳:成功 0,失敗 -1 (EINVAL)
int sigemptyset(sigset_t *set); // 清空集合
int sigfillset(sigset_t *set); // 填入所有信號
int sigaddset(sigset_t *set, int signum); // 加入信號
int sigdelset(sigset_t *set, int signum); // 移除信號
int sigismember(const sigset_t *set, int signum); // 測試成員(1=是, 0=否, -1=錯)
#include <stdio.h>
#include <signal.h>
void print_mask(const char *label) {
sigset_t set;
sigprocmask(0, NULL, &set);
printf("[%s] SIGINT=%d SIGTSTP=%d SIGTERM=%d\n",
label,
sigismember(&set, SIGINT),
sigismember(&set, SIGTSTP),
sigismember(&set, SIGTERM));
}
int main() {
sigset_t block_set;
sigemptyset(&block_set);
print_mask("Initial");
// 1. SIG_SETMASK 直接設定
sigaddset(&block_set, SIGINT);
sigaddset(&block_set, SIGTSTP);
sigprocmask(SIG_SETMASK, &block_set, NULL);
print_mask("After SETMASK INT+TSTP");
// 2. SIG_BLOCK 追加
sigaddset(&block_set, SIGTERM);
sigprocmask(SIG_BLOCK, &block_set, NULL);
print_mask("After BLOCK TERM");
// 3. SIG_UNBLOCK 移除
sigdelset(&block_set, SIGTERM);
sigprocmask(SIG_UNBLOCK, &block_set, NULL);
print_mask("After UNBLOCK TERM");
return 0;
}

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler(int sig) { printf("[Handler] Signal %d caught\n", sig); }
void print_mask(const char *label) { /* 同上 */ }
int main() {
sigset_t block_set, old_set, pend_mask;
signal(SIGINT, handler);
sigemptyset(&block_set);
sigaddset(&block_set, SIGINT);
sigaddset(&block_set, SIGTSTP);
printf("PID: %ld\n", (long)getpid());
// 1. 進入關鍵區:阻塞 SIGINT/SIGTSTP,保存舊屏蔽集
sigprocmask(SIG_SETMASK, &block_set, &old_set);
print_mask("Inside critical section (blocked)");
// 2. 模擬關鍵操作(5 秒內不被信號打擾)
sleep(5);
// 3. 檢查是否有待決信號
sigpending(&pend_mask);
if (sigismember(&pend_mask, SIGINT))
printf(">>> SIGINT was pending during critical section\n");
// 4. 離開關鍵區:恢復原始屏蔽集
sigprocmask(SIG_SETMASK, &old_set, NULL);
print_mask("After restoring mask");
printf("SIGINT unblocked, handler will run if pending\n");
sleep(6); // 給 handler 執行機會
return 0;
}
int sigpending(sigset_t *set);
// 將目前「已送達但被阻塞」的信號集複製到 set
// 配合 sigismember() 判斷特定信號是否待決
| 函數 | 適用範圍 | 標準 |
|---|---|---|
sigprocmask() | 單執行緒進程、主執行緒 | POSIX.1-2001 |
pthread_sigmask() | 多執行緒(每執行緒獨立屏蔽集) | POSIX.1-2001 |
多執行緒程式必須使用 pthread_sigmask(),sigprocmask() 行為未定義。
sigemptyset() 或 sigfillset()#define BLOCK_SIGNALS(mask, old) do { \
sigset_t _block; \
sigemptyset(&_block); \
sigaddset(&_block, SIGINT); \
sigaddset(&_block, SIGTERM); \
sigprocmask(SIG_SETMASK, &_block, &(old)); \
} while(0)
#define RESTORE_SIGNALS(old) sigprocmask(SIG_SETMASK, &(old), NULL)
// 使用範例
sigset_t old_mask;
BLOCK_SIGNALS(mask, old_mask);
// ... 關鍵操作 ...
RESTORE_SIGNALS(old_mask);