侧边栏壁纸
博主头像
colo

欲买桂花同载酒

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

编写一个捕获SIGINT信号的简单程序

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

题目

编写一个捕获SIGINT信号的简单程序

信息

  • 类型:问答
  • 难度:⭐

考点

信号处理基本概念,signal函数使用,信号处理函数编写

快速回答

实现步骤:

  1. 包含头文件#include <signal.h>
  2. 定义信号处理函数(如void handler(int sig) { ... }
  3. 使用signal(SIGINT, handler)注册处理函数
  4. 主函数中通过while(1)保持程序运行

核心代码:

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

void sigint_handler(int sig) {
    printf("Caught SIGINT!\n");
}

int main() {
    signal(SIGINT, sigint_handler);
    while(1) {
        sleep(1);
    }
    return 0;
}
## 解析

1. 原理说明

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

2. 完整代码示例

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

// 信号处理函数
void sigint_handler(int sig) {
    // 注意:printf不是异步安全函数,实际应用应避免使用
    printf("Caught SIGINT (Signal Number: %d)!\n", sig);
}

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);  // 避免CPU空转
    }
    return 0;
}

3. 关键点解析

  • signal函数signal(int sig, void (*handler)(int))用于注册信号处理函数,第一个参数是信号编号(如SIGINT),第二个是函数指针
  • 处理函数参数:信号处理函数接收一个整数参数,表示信号编号(SIGINT值为2)
  • 程序保持运行while(1)循环使程序持续运行以便测试,配合sleep减少资源占用

4. 最佳实践

  • 错误检查:始终检查signal()返回值(可能返回SIG_ERR
  • 异步安全函数:实际项目中应使用write代替printfprintf非线程安全)
  • 信号重置:某些系统在信号触发后会重置为默认行为,需在处理函数中重新注册

5. 常见错误

  • ❌ 忘记包含signal.h头文件
  • ❌ 处理函数签名错误(必须为void func(int)
  • ❌ 使用printf等非异步安全函数导致未定义行为
  • ❌ 主线程无等待逻辑导致程序立即退出

6. 扩展知识

  • 信号列表SIGTERM(终止请求)、SIGKILL(强制终止,不可捕获)、SIGSEGV(段错误)
  • 更现代的方法:推荐使用sigaction替代signal(提供更精确的控制)
  • 信号屏蔽:通过sigprocmask阻塞信号,防止关键代码段被中断
  • 多线程信号:在多线程程序中,信号处理是进程级别的,需特别设计