侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1824 篇文章
  • 累计收到 0 条评论

如何捕获并处理SIGINT信号?

2025-12-12 / 0 评论 / 3 阅读

题目

如何捕获并处理SIGINT信号?

信息

  • 类型:问答
  • 难度:⭐

考点

信号概念,信号处理函数注册,基本信号处理

快速回答

在C程序中捕获SIGINT信号(Ctrl+C触发)的步骤:

  1. 包含头文件:#include <signal.h>
  2. 定义信号处理函数:void handler(int sig) { ... }
  3. 使用signal(SIGINT, handler)注册处理函数
  4. 处理函数中应避免调用非异步安全函数
## 解析

1. 信号处理原理

信号是操作系统向进程发送的异步事件通知。当用户按下Ctrl+C时,系统会向当前前台进程发送SIGINT信号(中断信号),默认行为是终止进程。通过注册自定义处理函数,可以改变信号的响应行为。

2. 代码示例

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

// 自定义信号处理函数
void sigint_handler(int sig) {
    write(STDOUT_FILENO, "\nSIGINT received! Exiting...\n", 28);
    exit(0);  // 安全退出
}

int main() {
    // 注册信号处理函数
    if (signal(SIGINT, sigint_handler) == SIG_ERR) {
        perror("signal registration failed");
        return 1;
    }

    printf("Press Ctrl+C to test. PID: %d\n", getpid());
    while(1) {
        sleep(1);  // 保持程序运行
    }
    return 0;
}

3. 关键点说明

  • signal函数signal(int sig, void (*handler)(int))用于注册处理函数,第一个参数是信号编号,第二个是函数指针
  • 处理函数要求:应尽量简短,避免调用printf/malloc等非异步安全函数(本例使用write替代printf
  • 退出方式:处理函数中调用exit()而非return,确保进程终止

4. 最佳实践

  • 使用sigaction替代signal(更可靠,但本题要求简单)
  • 处理函数中仅设置标志位,在主循环中处理实际逻辑
  • 对全局变量使用volatile sig_atomic_t类型保证原子访问

5. 常见错误

  • 在处理函数中调用不可重入函数(如printf),可能导致死锁或崩溃
  • 忽略返回值检查:signal()失败时返回SIG_ERR
  • 长时间阻塞处理函数,影响其他信号响应

6. 扩展知识

  • 常见信号SIGTERM(终止请求)、SIGKILL(强制终止,不可捕获)、SIGSEGV(段错误)
  • 高级机制sigprocmask阻塞信号、sigaction设置更精细的处理参数
  • 信号来源:终端输入、硬件异常(如除零错误)、其他进程通过kill()发送