| 函數 | 用途 | 可攜帶資料 | 目標範圍 |
| kill(pid, sig) | 通用發送 | 否 | 單進程/進程組/所有進程 |
| raise(sig) | 發送給自身 | 否 | 當前進程 |
| sigqueue(pid, sig, val) | 發送實時信號攜帶資料 | 是 (union sigval) | 單進程 |
| alarm(sec) | 定時發送 SIGALRM | 否 | 當前進程 |
| setitimer(which, &itv, &oitv) | 高精度定時器 (ITIMER_REAL/VIRT/PROF) | 否 | 當前進程 |
| pthread_kill(tid, sig) | 發送給指定線程 | 否 | 單線程 |
| abort() | 發送 SIGABRT 並終止 | 否 | 當前進程 |
kill() 參數 pid 語義:
>0:指定 PID 進程
=0:同進程組所有進程
<-1:指定進程組 ID (=-pid) 所有進程
=-1:當前進程有權限發送的所有進程 (除 init)
六、信號集操作 (signal.h)
sigset_t set;
sigemptyset(&set); // 清空
sigfillset(&set); // 填滿所有信號
sigaddset(&set, SIGINT); // 加入
sigdelset(&set, SIGINT); // 移除
sigismember(&set, SIGINT); // 判斷成員
// 進程信號屏蔽字操作
sigprocmask(SIG_BLOCK, &set, &oldset); // 阻塞
sigprocmask(SIG_UNBLOCK, &set, &oldset); // 解除阻塞
sigprocmask(SIG_SETMASK, &set, &oldset); // 設定
// 等待信號 (原子解除阻塞並等待)
sigsuspend(&mask);
sigwait(&set, &sig);
sigwaitinfo(&set, &info);
sigtimedwait(&set, &info, &timeout);
七、核心信號處理流程
- 發送:
kill() → do_send_sig_info() → 將信號加入目標任務 pending 鏈表 (實時信號排隊、標準信號僅標記)
- 投遞: 進程從核心態返回用戶態前 (
exit_to_usermode_loop()) 檢查 TIF_SIGPENDING 標誌
- 處理:
do_signal() → 依 ka_handler 決定:忽略/預設動作/呼叫處理函數
- 處理函數執行: 構造 signal frame (ucontext_t、siginfo_t) → 切換到用戶堆疊 (SA_ONSTACK) → 執行 handler → 返回核心
sys_rt_sigreturn() → 恢復上下文
八、實時信號擴展細節 (POSIX.1b)
sigqueue() 發送時攜帶 union sigval { int sival_int; void *sival_ptr; }
- 處理函數簽名:
void handler(int sig, siginfo_t *info, void *ucontext)
siginfo_t 關鍵欄位:si_signo、si_code、si_pid、si_uid、si_value (攜帶資料)、si_addr (SIGSEGV 故障位址)
- 安裝時需設定
SA_SIGINFO 旗標並使用 sa_sigaction
- 實時信號支援多次排隊,核心維護
struct sigqueue 鏈表
九、信號安全與最佳實務
- Async-signal-safe 函數: 僅在 handler 中呼叫 POSIX 規定的安全函數 (write、_exit、sigaction、sigprocmask 等),嚴禁 malloc、printf、pthread_mutex_lock、非重入函數
- 全域變數: 僅存取
volatile sig_atomic_t 類型
- SA_RESTART: 讓被中斷的系統呼叫自動重啟 (read、write、wait 等)
- 信號與線程: 信號屬於進程,透過
pthread_sigmask() 控制各線程屏蔽字,特定線程可用 sigwait() 同步處理