C++信号处理
C 信号处理一、信号处理 基础概念1.1 什么是信号信号Signal是操作系统向进程发送的异步软中断。作用通知进程发生了异常、外部中断、终止请求等事件。特点异步触发随时可能打断程序正常执行流由内核、终端、其他进程、程序自身产生C 兼容 C 标准信号机制头文件#includecsignal1.2 信号常见触发来源终端按键Ctrl C、Ctrl \程序运行异常除零错误、非法内存访问、非法指令系统内核进程被杀、超时、管道断开代码主动调用raise()、abort()其他进程发送信号Linuxkill命令1.3 信号处理核心流程定义信号回调处理函数使用signal()注册信号与回调信号到来时系统自动中断程序执行回调回调结束后默认恢复程序执行或退出二、C 标准预定义信号列表所有信号均定义在csignal头文件中信号常量值含义触发场景SIGINT2终端中断信号Ctrl CSIGABRT6程序异常终止调用abort()SIGFPE8浮点算术异常除零、数值溢出SIGILL4非法硬件指令执行无效机器指令SIGSEGV11段错误非法内存访问、野指针SIGTERM15软件终止请求系统/其他进程请求结束程序SIGQUIT3终端退出信号Ctrl \SIGALRM14闹钟超时信号定时器到时SIGBUS7总线错误内存地址对齐错误注意部分信号不能被捕获或忽略如 LinuxSIGKILL。三、signal() 信号注册函数详解3.1 函数原型void(*signal(intsig,void(*handler)(int)))(int);拆解说明第一个参数sig要监听的信号编号第二个参数handler信号处理函数指针返回值返回旧的处理函数指针3.2 信号处理函数规范固定格式必须严格遵守void回调函数名(intsignum){// signum当前触发的信号值// 信号处理逻辑}3.3 系统内置处理方式无需自定义函数直接使用系统宏SIG_DFL默认处理触发后系统默认行为终止程序、产生核心转储等SIG_IGN忽略该信号收到信号不做任何处理程序继续运行使用示例// 忽略 CtrlCsignal(SIGINT,SIG_IGN);// 恢复系统默认处理signal(SIGINT,SIG_DFL);四、raise() 主动发送信号4.1 函数原型intraise(intsig);功能进程内部主动向自身发送一个指定信号返回值成功返回 0失败返回非0常用于模拟异常、测试信号回调逻辑4.2 abort() 主动异常终止voidabort(void);内部会触发SIGABRT信号程序异常终止可生成 core 崩溃日志五、完整实战案例案例1捕获 CtrlC 优雅退出#includeiostream#includecsignal#includeunistd.husingnamespacestd;voidsigHandler(intsig){cout\nendl;cout 捕获到信号sig (CtrlC)endl;cout 开始释放资源、保存数据...endl;cout 程序安全退出endl;coutendl;// 收尾后退出exit(EXIT_SUCCESS);}intmain(){// 注册 SIGINT 信号回调signal(SIGINT,sigHandler);cout程序已启动按 CtrlC 触发退出endl;while(true){cout程序正常运行中...endl;sleep(1);}return0;}案例2忽略信号 恢复默认处理#includeiostream#includecsignal#includeunistd.husingnamespacestd;intmain(){// 忽略 CtrlCsignal(SIGINT,SIG_IGN);cout已忽略 CtrlC按 CtrlC 无效endl;sleep(5);// 恢复系统默认处理signal(SIGINT,SIG_DFL);cout5秒后恢复默认现在 CtrlC 可终止程序endl;while(true)sleep(1);return0;}案例3程序主动 raise 触发信号#includeiostream#includecsignalusingnamespacestd;voidcallback(intsig){cout回调触发信号编号sigendl;}intmain(){signal(SIGINT,callback);cout程序主动发送 SIGINT 信号endl;// 主动给自己发信号raise(SIGINT);cout信号处理完毕继续执行后续代码endl;return0;}案例4同时注册捕获多个信号#includeiostream#includecsignal#includeunistd.husingnamespacestd;voidmultiSigHandler(intsig){switch(sig){caseSIGINT:cout\n收到 CtrlC 中断endl;break;caseSIGSEGV:cout\n捕获段错误非法内存访问endl;exit(1);break;caseSIGFPE:cout\n捕获算术异常除零/溢出endl;exit(1);break;default:cout\n收到未知信号sigendl;}}intmain(){// 一次性注册多个信号共用同一个处理函数signal(SIGINT,multiSigHandler);signal(SIGSEGV,multiSigHandler);signal(SIGFPE,multiSigHandler);while(true){cout多信号监听中...endl;sleep(2);}return0;}六、信号处理函数 严格限制工程必看信号回调函数不能随意写代码有严格安全限制禁止调用非可重入函数cout、printf、malloc、文件IO 等尽量少用禁止复杂业务逻辑、循环、耗时操作不要在回调中嵌套信号注册建议只做标记全局状态、简单日志、设置退出标志信号是异步的极易引发竞态条件多线程环境慎用推荐最佳实践信号回调只修改一个全局标记变量主循环检测标记再做优雅退出和资源释放。七、跨平台兼容差异Linux / macOS信号机制完整支持全部标准信号sleep(秒)unistd.h支持kill命令发信号段错误可生成 core 文件用于崩溃分析Windows仅支持子集常用信号SIGINT、SIGABRT、SIGFPE、SIGILL、SIGSEGV睡眠函数Sleep(毫秒)头文件windows.h不支持 Unix 大量扩展信号无 core 转储机制八、工程实际应用场景后台服务程序捕获CtrlC优雅退出关闭socket、保存配置、释放资源崩溃防护捕获段错误、算术异常记录崩溃现场日志守护进程监听终止信号做重启或善后处理调试定位捕获异常信号打印行号、文件信息定时任务利用SIGALRM实现简单定时器九、核心知识点总结信号是操作系统发给进程的异步软中断signal()注册信号回调raise()主动发信号可使用SIG_DFL默认处理、SIG_IGN忽略信号常用信号SIGINT、SIGSEGV、SIGFPE、SIGABRT、SIGTERM信号回调必须精简、可重入禁止复杂逻辑适合做优雅退出、崩溃捕获、资源善后、服务守护Linux 与 Windows 信号子集有差异跨平台需兼容适配。