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

C標準庫參考指南(9):signal.h 信號處理接口完整解析

     編輯:關於C語言

前言:signal.h——異步事件的捕獲與響應

signal.h 定義了進程處理異步信號的標準接口:信號編號宏、處理動作常量、signal() 註冊處理函數、raise() 發送信號、sig_atomic_t 信號安全類型。本文系統整理所有宏、函數原型、語義規則、信號安全編程鐵律、經典示例。

一、 宏常量與類型

1. 處理動作常量

  • SIG_DFL:默認動作 (終止/棄核/忽略/停止/繼續)。
  • SIG_IGN:忽略信號。
  • SIG_ERR:signal() 失敗返回值。

2. 標準信號編號 (ISO C 保證存在)

宏含義典型來源默認動作
SIGABRT異常終止abort()終止+棄核
SIGFPE浮點/算術異常除零、溢出終止+棄核
SIGILL非法指令壞代碼/棧破壞終止+棄核
SIGINT終端中斷Ctrl+C終止
SIGSEGV非法內存訪問空指針/越界終止+棄核
SIGTERM終止請求kill 命令終止

POSIX 擴展信號 (SIGCHLD, SIGPIPE, SIGALRM, SIGUSR1/2...) 不在標準 C 範圍內。

3. sig_atomic_t

整數類型 (通常 int),**保證讀寫原子性** (無中斷),用於信號處理函數與主程序共享標志變量。

二、 核心函數

1. signal:註冊處理函數

void (*signal(int sig, void (*func)(int)))(int);
  • sig:信號編號 (上表宏)。
  • func:處理函數指針,簽名 void handler(int sig)。可傳 SIG_DFL/SIG_IGN。
  • **語義**:設置 sig 的處理方式為 func。返回**之前**的處理函數指針 (或 SIG_DFL/IGN/ERR)。
  • **返回**:成功返回舊處理器,失敗返回 SIG_ERR 並置 errno。
  • **信號處理函數約束**:
    • 只能調用**異步信號安全函數** (POSIX 列表:write/_exit/sigaction 等,**不可調用 printf/malloc/lock**)。
    • 修改共享變量必用 volatile sig_atomic_t。
    • 返回後程序從中斷處繼續 (除非 SIGFPE` 行為未定義)。

2. raise:向自身發送信號

int raise(int sig);
  • 同步發送 sig 給調用進程/線程。
  • 成功返回 0,失敗非 0。

三、 經典示例:捕獲 SIGINT (Ctrl+C)

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

void catch_function(int signal) {
    printf("Interactive attention signal caught.\n");
    // 註意:printf 非信號安全!僅教學演示。生產用 write(STDOUT_FILENO, ...)
}

int main(void) {
    if (signal(SIGINT, catch_function) == SIG_ERR) {
        fprintf(stderr, "An error occured while setting a signal handler.\n");
        exit(EXIT_FAILURE);
    }
    printf("Raising the interactive attention signal.\n");
    if (raise(SIGINT) != 0) {
        fprintf(stderr, "Error raising the signal.\n");
        exit(EXIT_FAILURE);
    }
    printf("Exiting.\n");
    return 0;
}

輸出:

Raising the interactive attention signal.
Interactive attention signal caught.
Exiting.

四、 信號安全編程鐵律 (生產級必讀)

  1. 處理函數極簡:只修改 volatile sig_atomic_t 標志,或調用 write/_exit/kill/sigprocmask 等安全函數。
  2. 主循環輪詢標志:while (!quit_flag) { ... },在安全點處理複雜邏輯。
  3. 阻塞關鍵區:sigprocmask(SIG_BLOCK, ...) 保護非原子操作。
  4. 避免競態:檢查標志 → 阻塞信號 → 處理 → 解除阻塞,或用 sigsuspend 原子等待。
  5. 重入風險:信號處理函數可能中斷自身 (同一信號再次遞達),共享數據結構必須無鎖或可重入。
  6. 現代替代:sigaction() (POSIX) 提供更精確控制 (SA_RESTART, SA_SIGINFO, SA_NODEFER),**強烈建議新代碼使用 sigaction**。

五、 總結

signal.h 是 C 標準庫中最「危險」的頭文件:**接口簡單但語義陷阱深**。理解 signal() 返回舊處理器、處理函數異步安全約束、sig_atomic_t 原子性保證、raise() 同步發送機制,並**遷移至 sigaction()**,是編寫健壯信號驅動程序的必經之路。

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