在 Linux 下用 C++ 处理信号(signal),常见做法有 signal()、sigaction(),以及更高级的 signalfd / self-pipe 等方式。下面按“从简单到推荐”给你一个完整说明。
信号是 Linux 中进程间异步通信的一种方式,例如:
| 信号 | 含义 |
|---|---|
| SIGINT | Ctrl+C |
| SIGTERM | kill 默认信号 |
| SIGKILL | 不可捕获 |
| SIGSEGV | 段错误 |
| SIGPIPE | 管道破裂 |
| SIGCHLD | 子进程状态变化 |
signal()(不推荐)#include <iostream>
#include <csignal>
void handler(int sig) {
std::cout << "catch signal: " << sig << std::endl;
}
int main() {
signal(SIGINT, handler);
while (true) {}
}
sigaction()(标准做法)#include <iostream>
#include <csignal>
#include <unistd.h>
void signal_handler(int sig) {
if (sig == SIGINT) {
std::cout << "Caught SIGINT" << std::endl;
} else if (sig == SIGTERM) {
std::cout << "Caught SIGTERM, exiting..." << std::endl;
_exit(0);
}
}
int main() {
struct sigaction sa{};
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGINT, &sa, nullptr);
sigaction(SIGTERM, &sa, nullptr);
while (true) {
pause(); // 等待信号
}
}
✅ 可移植
✅ 行为明确
✅ 可屏蔽其他信号
malloc / freecout << ...(不是 async-signal-safe)✅ 信号处理函数应只做“最小操作”
volatile sig_atomic_t#include <csignal>
#include <iostream>
#include <unistd.h>
volatile sig_atomic_t g_running = 1;
void handler(int) {
g_running = 0;
}
int main() {
struct sigaction sa{};
sa.sa_handler = handler;
sigaction(SIGINT, &sa, nullptr);
while (g_running) {
// 主循环
sleep(1);
}
std::cout << "exit cleanly" << std::endl;
}
✅ 安全
✅ 简单
✅ 常用于服务器程序
把信号转成文件描述符,可配合 epoll
#include <sys/signalfd.h>
#include <signal.h>
#include <unistd.h>
#include <iostream>
int main() {
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigprocmask(SIG_BLOCK, &mask, nullptr);
int sfd = signalfd(-1, &mask, 0);
while (true) {
struct signalfd_siginfo si;
read(sfd, &si, sizeof(si));
std::cout << "Got signal: " << si.ssi_signo << std::endl;
}
}
✅ 适合事件驱动程序
✅ 无信号处理函数限制
(如果你需要我可以给示例)
| 信号 | 是否可捕获 |
|---|---|
| SIGINT | ✅ |
| SIGTERM | ✅ |
| SIGKILL | ❌ |
| SIGSTOP | ❌ |
| SIGSEGV | ✅(调试用) |
| SIGPIPE | ✅(通常忽略) |
✅ 新代码用 sigaction()
✅ 信号处理函数只设标志
✅ 服务器程序用 signalfd + epoll
❌ 不用 signal()
如果你愿意,可以告诉我:
我可以给你一个生产级模板。