Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 信號機制深度解析:類型、發送、處理、可靠性與實時擴展

編輯:Linux 教學

信號是 Linux 進程間通訊 (IPC) 中唯一的非同步通知機制。本文系統解析信號本質、分類 (可靠/不可靠、實時/非實時)、發送與安裝 API、進程響應流程、信號集操作、核心處理路徑與實時擴展細節。

一、信號本質與來源

  • 本質: 軟體層面對硬體中斷的模擬,非同步事件通知
  • 異步性: 進程無需等待、無法預知到達時刻
  • 兩大來源:
    • 硬體:鍵盤中斷 (SIGINT)、除零錯誤 (SIGFPE)、非法記憶體存取 (SIGSEGV)
    • 軟體:kill()、raise()、alarm()、setitimer()、sigqueue()、Shell 作業控制

二、信號分類體系

2.1 依可靠性分類

類別信號值範圍特徵代表信號
不可靠信號1 ~ SIGRTMIN-1 (通常 1-31)不排隊、可能丟失、早期 Unix 遺留SIGHUP(1), SIGINT(2), SIGQUIT(3), SIGKILL(9), SIGSEGV(11), SIGTERM(15), SIGCHLD(17)
可靠信號SIGRTMIN ~ SIGRTMAX (通常 32-64)支援排隊、不丟失、POSIX.4 實時擴展SIGRTMIN(32) ~ SIGRTMAX(64)

關鍵澄清: 可靠性僅由信號值決定,與安裝函數 (signal()/sigaction()) 或發送函數 (kill()/sigqueue()) 無關。現代 Linux signal() 內部實現基於 sigaction(),不可靠信號也不再重置處理器。

2.2 依實時性分類

  • 非實時信號 (標準信號): 1-31,固定用途、預設動作、不排隊
  • 實時信號: 32-64,用戶自定義、支援排隊、可攜帶資料 (sigval)

兩種分類維度完全對應:非實時 = 不可靠,實時 = 可靠。

三、進程對信號的三種響應

四、信號安裝 API 對比

方式描述限制
忽略不做任何處理SIGKILL、SIGSTOP 不可忽略
捕捉註冊處理函數,信號到達時執行處理函數需為 async-signal-safe
預設動作核心預設處理 (終止/棄核/停止/繼續/忽略)實時信號預設動作為終止進程

sigaction 結構體:


struct sigaction {
    void     (*sa_handler)(int);           // 普通處理器
    void     (*sa_sigaction)(int, siginfo_t *, void *); // 擴展處理器
    sigset_t   sa_mask;                    // 執行期間阻塞的信號集
    int        sa_flags;                   // SA_* 旗標
    void     (*sa_restorer)(void);         // 過時欄位
};

五、信號發送 API

特性signal()sigaction()
標準ANSI C / POSIX.1POSIX.1
可攜帶資料否是 (sa_sigaction + SA_SIGINFO)
信號屏蔽控制無完整 (sa_mask)
Flags 控制無豐富 (SA_RESTART, SA_NOCLDSTOP, SA_SIGINFO, SA_NODEFER, SA_RESETHAND, SA_ONSTACK)
可靠信號支援支援排隊支援排隊
推薦程度簡單場景生產環境首選

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);

七、核心信號處理流程

  1. 發送: kill() → do_send_sig_info() → 將信號加入目標任務 pending 鏈表 (實時信號排隊、標準信號僅標記)
  2. 投遞: 進程從核心態返回用戶態前 (exit_to_usermode_loop()) 檢查 TIF_SIGPENDING 標誌
  3. 處理: do_signal() → 依 ka_handler 決定:忽略/預設動作/呼叫處理函數
  4. 處理函數執行: 構造 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() 同步處理
Copyright © Windows教程網 All Rights Reserved
函數用途可攜帶資料目標範圍
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 並終止否當前進程