掌握 C++ 信号处理:安全中断管理与优雅程序终止
信号概述
信号是操作系统发送给进程的中断通知,可能导致程序过早终止。在 UNIX、Linux、macOS 或 Windows 系统上,按下 Ctrl+C 即可产生中断信号。
虽然某些信号无法被程序捕获,但 C++ 标准库 <csignal> 定义了一系列可捕获的信号,使程序能根据信号类型采取相应措施。
常见可捕获信号
| 序号 | 信号与说明 |
|---|---|
| 1 | SIGABRT:程序异常终止,如调用 abort()。 |
| 2 | SIGFPE:算术运算错误,如除零或溢出。 |
| 3 | SIGILL:检测到非法指令。 |
| 4 | SIGINT:接收到交互式注意信号(通常为 Ctrl+C)。 |
| 5 | SIGSEGV:非法内存访问(段错误)。 |
| 6 | SIGTERM:发送给程序的终止请求。 |
signal() 函数
C++ 信号处理库提供 signal() 函数用于捕获异常事件,其声明如下:
void (*signal(int sig, void (*func)(int)))(int);
简化理解:该函数接受两个参数——信号编号(整数)和指向信号处理函数的指针。
示例:捕获 SIGINT 信号
#include <iostream>
#include <csignal>
#include <unistd.h>
using namespace std;
void signalHandler(int signum) {
cout << "Interrupt signal (" << signum << ") received.\n";
// 清理并关闭资源
exit(signum);
}
int main() {
// 注册 SIGINT 信号及其处理函数
signal(SIGINT, signalHandler);
while (true) {
cout << "Going to sleep...." << endl;
sleep(1);
}
return 0;
}
编译运行后,程序会周期性输出 "Going to sleep...."。按下 Ctrl+C 时,程序捕获信号并输出:
Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.
raise() 函数
程序可通过 raise() 函数主动发送信号,语法如下:
int raise(int sig);
参数 sig 为信号编号,可发送 SIGINT、SIGABRT、SIGFPE、SIGILL、SIGSEGV、SIGTERM、SIGHUP 等信号。
示例:内部触发 SIGINT
#include <iostream>
#include <csignal>
#include <unistd.h>
using namespace std;
void signalHandler(int signum) {
cout << "Interrupt signal (" << signum << ") received.\n";
exit(signum);
}
int main() {
int i = 0;
signal(SIGINT, signalHandler);
while (++i) {
cout << "Going to sleep...." << endl;
if (i == 3) {
raise(SIGINT); // 主动触发信号
}
sleep(1);
}
return 0;
}
程序运行到第 3 次循环时自动触发信号并退出:
Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.
最佳实践建议
- 信号处理函数应保持简短,仅设置标志或执行极简清理,避免调用非异步安全函数。
- 复杂的清理工作应在主循环中通过检查标志位完成。
- 多线程程序中需注意信号处理的线程安全性,推荐使用
sigaction()替代signal()。
C语言
- 深入理解 C++ 数据类型:基础类型、修饰符与最佳实践
- 掌握 C++ 运算符:六大类型全解析与实战示例
- C++ 注释最佳实践:编写可读、可维护代码的注释艺术
- C++ 类模板实战指南:编写灵活的类型无关代码
- C语言文件处理完全指南:fopen、fprintf、fread 与 fseek
- C++ 异常处理实战:try、catch、throw 完整指南与示例
- C 语言错误处理最佳实践:errno、perror 与 strerror 详解
- C++编程语言:核心特性全景解析
- C++常量与字面量完全手册:类型、语法与最佳实践
- C++运算符大全:算术/关系/逻辑/位/赋值/杂项与优先级结合性
- C++数值类型实战指南:基本类型、数学函数与随机数生成
- C++引用详解:核心概念、与指针三大差异及函数参数/返回值应用