温馨提示×

linux c++如何捕获信号

小樊
40
2026-09-20 10:31:12
栏目: 编程语言

在 Linux 下用 C/C++ 捕获(处理)信号,通常使用 signal() 或更推荐、更可靠的 sigaction()。下面从基础到推荐做法给你说明。


一、信号基本概念

信号(signal)是 Linux 中进程间异步通知机制,例如:

  • SIGINT (Ctrl+C)
  • SIGTERM (终止)
  • SIGSEGV (段错误)
  • SIGUSR1 / SIGUSR2 (用户自定义)

二、最简单方式:signal()

#include <iostream>
#include <csignal>

void handler(int sig) {
    std::cout << "Received signal: " << sig << std::endl;
}

int main() {
    signal(SIGINT, handler);
    while (true) {}
}

✅ 简单
❌ 可移植性差,行为在不同 UNIX 上不一致


三、推荐方式:sigaction()

1️⃣ 基本用法

#include <iostream>
#include <csignal>
#include <unistd.h>

void handler(int sig) {
    std::cout << "Caught signal: " << sig << std::endl;
}

int main() {
    struct sigaction sa{};
    sa.sa_handler = handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    sigaction(SIGINT, &sa, nullptr);

    while (true) {
        pause();  // 等待信号
    }
}

2️⃣ 带附加信息的信号处理

void handler(int sig, siginfo_t* info, void* context) {
    std::cout << "Signal: " << sig
              << ", from PID: " << info->si_pid << std::endl;
}

int main() {
    struct sigaction sa{};
    sa.sa_sigaction = handler;
    sa.sa_flags = SA_SIGINFO;

    sigaction(SIGUSR1, &sa, nullptr);
}

四、信号处理中的注意事项(非常重要)

❗ 只能调用「异步信号安全」函数

不能在信号处理函数中:

  • printf
  • new / delete
  • std::cout
  • 加锁(可能死锁)

✅ 推荐做法:

  • 设置 volatile sig_atomic_t 标志
volatile sig_atomic_t stop = 0;

void handler(int) {
    stop = 1;
}

int main() {
    signal(SIGINT, handler);
    while (!stop) {
        // 正常逻辑
    }
}

五、常见信号示例

signal(SIGINT, handler);   // Ctrl+C
signal(SIGTERM, handler); // kill
signal(SIGSEGV, handler); // 段错误(谨慎)

六、阻塞信号(防止竞态)

sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_BLOCK, &set, nullptr);

七、总结建议

生产环境用 sigaction
信号处理函数越简单越好
主循环检查标志位,不要用复杂逻辑

如果你有具体场景(守护进程 / 多线程 / 实时信号 / C++11),我可以给你更合适的示例。

0