跳转到内容

C 语言信号处理

来自代码酷
Admin留言 | 贡献2025年4月29日 (二) 04:45的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)


简介

信号处理是C语言标准库(<signal.h>)提供的一种进程间通信机制,允许操作系统或用户进程向目标进程发送异步事件通知。信号可以用于处理异常、中断请求或实现简单的进程控制。在UNIX/Linux系统中,信号是系统级事件的基本通知方式。

信号处理的核心功能包括:

  • 发送信号(如通过kill()系统调用)
  • 捕获并自定义信号处理行为
  • 忽略或恢复默认信号行为

信号类型

常见标准信号(定义在<signal.h>中):

标准信号列表(部分)
信号名 描述
SIGINT 2 终端中断(如Ctrl+C)
SIGSEGV 11 无效内存访问
SIGTERM 15 终止请求
SIGALRM 14 定时器超时

基本用法

信号处理函数

使用signal()函数注册信号处理器:

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

void handler(int sig) {
    printf("Received signal: %d\n", sig);
}

int main() {
    signal(SIGINT, handler);  // 注册SIGINT处理器
    while(1) {
        printf("Running...\n");
        sleep(1);
    }
    return 0;
}

输出示例

Running...
Running...
^CReceived signal: 2  # 用户按下Ctrl+C
Running...
...

高级信号处理

更安全的sigaction()函数:

struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;

sigaction(SIGINT, &sa, NULL);

实际案例

定时器实现

使用SIGALRM创建简单定时器:

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

void alarm_handler(int sig) {
    printf("Timer expired!\n");
}

int main() {
    signal(SIGALRM, alarm_handler);
    alarm(5);  // 设置5秒定时器
    pause();   // 等待信号
    return 0;
}

多线程信号处理

在多线程程序中,信号处理需特别注意:

pthread_sigmask(SIG_BLOCK, &mask, NULL);  // 阻塞信号
// 创建线程...
pthread_sigmask(SIG_UNBLOCK, &mask, NULL); // 在主线程处理信号

信号处理流程

flowchart TD A[信号产生] --> B{信号处理方式} B -->|默认| C[执行系统默认操作] B -->|忽略| D[丢弃信号] B -->|自定义| E[调用用户处理函数] E --> F[处理函数返回后恢复执行]

数学基础

信号处理涉及中断概率计算。假设信号到达服从泊松分布: P(k)=λkeλk! 其中:

  • λ为单位时间平均信号数
  • k为实际到达信号数

注意事项

1. 信号处理函数应是可重入的(避免使用非异步安全函数如printf()) 2. 某些信号(如SIGKILL)不能被捕获或忽略 3. 信号可能中断系统调用(需检查errno == EINTR

扩展阅读

  • UNIX信号机制发展历史
  • 实时信号(SIGRTMINSIGRTMAX
  • 信号与进程状态的关系