首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

信號處理防失靈指南:從 ANSI signal.h 到 POSIX sigaction 完整解析

     編輯:關於VC++

摘要

本文剖析 ANSI <signal.h> 庫並示範其介面用法,進而討論 POSIX 信號處理 API。

信號處理基礎

信號似硬體中斷,使進程跳出當前控制流執行特定行為,處理完恢復原處繼續。預設某些信號導致進程終止 (如存取非擁有記憶體觸發 SIGSEGV)。調試、模擬、事務系統必須處理此類信號讓進程繼續執行。對策:安裝處理器捕獲信號。

第一步:建立信號處理器

信號為核心傳給進程的整數。進程收到信號可:忽略、讓核心執行預設動作、捕獲 (核心將控制權交給處理常式,執行完恢復)。

signal() 為給定信號註冊處理常式:

typedef void (*handler)(void);
void * signal(int signum, handler);
  • 第一參數:信號編碼。
  • 第二參數:使用者定義函數位址,信號產生時呼叫。
  • 特殊值:SIG_IGN (忽略,SIGKILL/SIGSTOP 不可忽略/捕獲/阻塞)、SIG_DFL (預設動作)。

第二步:發送信號

  1. 進程呼叫 raise() 顯式發送給自己。
  2. 其他進程發送,如 kill() 系統呼叫或 Perl 腳本。
  3. 核心發送,如存取非法記憶體、系統關機期間存取記憶體。

第三步:產生與處理信號範例

#include <csignal>
#include <iostream>
using namespace std;
void term(int sig) {
    // 必要清理操作
    cout << "handling signal no." << sig << endl;
}
int main() {
    signal(SIGTERM, term); // 註冊 SIGTERM 處理器
    raise(SIGTERM);        // 觸發 term()
}

ANSI <signal.h> 的局限

進程準備執行 SIGx 處理常式時又收到同一信號怎麼辦?

  • 讓核心中斷並重跑處理常式 → 需可重入 (re-entrant) 處理常式,設計極難。
  • ANSI C 對策:執行使用者處理常式前,將處理常式重置為 SIG_DFL。問題:兩信號快速產生時,核心跑第一個處理常式,第二個執行預設動作 → 可能終止進程。

過去 30 年出現多種信號處理框架,POSIX 信號 API 最成熟可移植。

POSIX 信號 API

操作打包在 sigset_t 中的信號集:

  • sigemptyset:清空集合
  • sigfillset:填入所有可用信號
  • sigaddset:加入信號
  • sigdelset:移除信號
  • sigismember:檢查信號是否在集合中

sigaction():註冊處理常式

int sigaction(int signum, struct sigaction *act, struct sigaction *prev);

sigaction 結構描述核心處理 signum 的資訊:

struct sigaction {
    sighandler_t sa_handler;   // 處理函數位址 (帶 int 參數,無回傳),或 SIG_DFL/SIG_IGN
    sigset_t sa_mask;          // 阻塞信號清單
    unsigned long sa_flags;    // 阻塞模式
    void (*sa_restorer)(void); // 未使用
};

POSIX 額外特性:阻塞信號與獲取未決信號

阻塞信號:sigprocmask()

int sigprocmask(int mode, const sigset_t* newmask, sigset_t* oldmask);
  • SIG_BLOCK:將 newmask 信號加入當前阻塞罩。
  • SIG_UNBLOCK:從阻塞罩移除 newmask 信號。
  • SIG_SETMASK:僅阻塞 newmask 信號。

獲取未決信號:sigpending()

被阻塞信號處於等待狀態,稱「未決信號」,可用 sigpending(sigset_t *pset) 獲取。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved