news 2026/4/16 10:16:34

当linux触发panic后进行自定义收尾回调处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
当linux触发panic后进行自定义收尾回调处理


大家好,我是bug菌~

如何在内核panic时注册回调函数,有时候系统panic后需要进行一些收尾工作:

完整的示例代码

#include<linux/notifier.h>#include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h>#include<linux/reboot.h>// 可能需要#include<linux/delay.h>staticintmy_panic_handler(structnotifier_block*nb,unsignedlongreason,void*arg){// reason 参数表示panic的原因,可以是:// PANIC_REASON_GENERIC// PANIC_REASON_HW_BUG// PANIC_REASON_HUNG_TASK// PANIC_REASON_STACKLEAK// PANIC_REASON_CORRUPTED_STACK// PANIC_REASON_CGROUP_DESTROY_FAILEDpr_emerg("Kernel panic detected in my module!\n");// 获取panic消息(如果有)constchar*msg=(constchar*)arg;if(msg)pr_emerg("Panic message: %s\n",msg);// 紧急操作 - 注意:// 1. 不要分配内存(如kmalloc)// 2. 不要获取可能已持有的锁// 3. 避免复杂操作,系统可能已不稳定// 示例:通知硬件模块// hardware_emergency_shutdown();// 示例:保存关键数据到持久存储// emergency_data_flush();// 示例:发送信号到其他处理器// send_ipi_to_all_cpus(EMERGENCY_IPI);returnNOTIFY_DONE;}staticstructnotifier_blockpanic_nb={.notifier_call=my_panic_handler,.priority=INT_MAX,// 优先级:数字越大,优先级越高// 或者使用 .next = NULL,};staticint__initpanic_module_init(void){intret;pr_info("Registering panic notifier\n");// 注册到panic通知链ret=atomic_notifier_chain_register(&panic_notifier_list,&panic_nb);if(ret){pr_err("Failed to register panic notifier: %d\n",ret);returnret;}// 也可以注册到重启通知链,如果系统会重启// register_reboot_notifier(&reboot_nb);return0;}staticvoid__exitpanic_module_exit(void){pr_info("Unregistering panic notifier\n");// 注销通知atomic_notifier_chain_unregister(&panic_notifier_list,&panic_nb);}module_init(panic_module_init);module_exit(panic_module_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Your Name");MODULE_DESCRIPTION("Kernel panic handler module");

关键注意事项

  1. 操作限制
// 在panic处理程序中应避免:-内存分配(kmalloc,vmalloc等)-获取锁(mutex_lock,spin_lock等)-调度相关操作(schedule,sleep等)-复杂I/O操作-可能失败的操作// 应该做:-简单的硬件寄存器操作-紧急状态保存到非易失存储-发送硬件信号或中断-打印关键调试信息
  1. 优先级控制
staticstructnotifier_blockpanic_nb={.notifier_call=my_panic_handler,.priority=INT_MAX,// 最高优先级// 或者:// .priority = 0, // 最低优先级// .priority = 100, // 自定义优先级};
  1. 多处理器注意事项
staticintmy_panic_handler(structnotifier_block*nb,unsignedlongreason,void*arg){// panic处理程序在所有CPU上都会运行!// 使用 smp_processor_id() 获取当前CPU IDintcpu=smp_processor_id();// 如果是第一个panic的CPU,执行清理操作if(cpu==0){// 主清理操作}else{// 从处理器只需简单清理}returnNOTIFY_DONE;}
  1. 系统挂起处理
#include<linux/freezer.h>staticintmy_panic_handler(structnotifier_block*nb,unsignedlongreason,void*arg){// 尝试解冻进程(如果需要)thaw_processes();// 停止所有可停止的进程// emergency_ops();returnNOTIFY_DONE;}

调试技巧

  1. 添加调试信息
staticintmy_panic_handler(structnotifier_block*nb,unsignedlongreason,void*arg){pr_emerg("=== My Module Panic Handler ===\n");pr_emerg("CPU: %d\n",smp_processor_id());pr_emerg("Panic reason: %lu\n",reason);pr_emerg("Stack trace:\n");dump_stack();// 打印堆栈跟踪// 保存寄存器状态show_regs(get_irq_regs());returnNOTIFY_DONE;}
  1. 使用Kprobes进行测试
// 可以通过Kprobes触发panic来测试#include<linux/kprobes.h>staticstructkprobekp={.symbol_name="panic",};staticinthandler_pre(structkprobe*p,structpt_regs*regs){pr_info("About to trigger panic\n");return0;}staticint__inittest_init(void){intret;kp.pre_handler=handler_pre;ret=register_kprobe(&kp);// 之后可以手动触发panic来测试// panic("Test panic");returnret;}

替代方案

  1. 使用die_notifier
#include<linux/kdebug.h>staticintmy_die_handler(structnotifier_block*self,unsignedlongval,void*data){structdie_args*args=data;if(val==DIE_OOPS||val==DIE_PANIC){pr_emerg("Die notifier triggered\n");}returnNOTIFY_DONE;}staticstructnotifier_blockdie_nb={.notifier_call=my_die_handler,};
  1. 使用module参数控制
staticbool enable_panic_handler=true;module_param(enable_panic_handler,bool,0644);staticintmy_panic_handler(structnotifier_block*nb,unsignedlongreason,void*arg){if(!enable_panic_handler)returnNOTIFY_DONE;// 处理逻辑returnNOTIFY_DONE;}

最佳实践

  1. 保持处理程序简单 - 系统已不稳定,复杂操作可能失败
  2. 避免依赖其他模块 - 其他模块可能已经卸载或损坏
  3. 记录关键状态 - 保存到不易丢失的存储中
  4. 考虑硬件状态 - 确保硬件处于安全状态
  5. 测试充分 - 在实际panic场景测试,而不仅仅是模拟

以上就是我的一些技巧和注意事项分享了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 12:35:11

Linux内核触发Softlockup和Hung task异常异同

大家好&#xff0c;我是bug菌~ 在Linux内核中&#xff0c;Softlockup和Hung task都是任务调度异常的情况&#xff0c;但它们的检测机制、触发条件和关注点有所不同&#xff1a; Softlockup&#xff08;软锁死&#xff09; 定义指某个CPU核心上的内核任务长时间占用CPU而不调度…

作者头像 李华
网站建设 2026/4/13 23:33:06

终极指南:如何用ComfyUI-Lumi-Batcher快速提升AI图像生成效率

终极指南&#xff1a;如何用ComfyUI-Lumi-Batcher快速提升AI图像生成效率 【免费下载链接】comfyui-lumi-batcher ComfyUI Lumi Batcher is a batch processing extension plugin designed for ComfyUI, aiming to improve workflow debugging efficiency. Traditional debuggi…

作者头像 李华
网站建设 2026/4/15 11:44:17

3步极速部署:自然语言SQL转换框架完整实践指南

3步极速部署&#xff1a;自然语言SQL转换框架完整实践指南 【免费下载链接】XiYan-SQL A MULTI-GENERATOR ENSEMBLE FRAMEWORK FOR NATURAL LANGUAGE TO SQL 项目地址: https://gitcode.com/gh_mirrors/xiy/XiYan-SQL 在当今数据驱动的时代&#xff0c;如何让非技术用户…

作者头像 李华
网站建设 2026/4/15 18:42:25

Beta Sprint 1 冲刺日志(前端组)

EE308FZ - 6th Assignment - PoopCare Sprint Essays - Frontend Group Beta Sprint 1 冲刺日志&#xff08;前端组&#xff09;Course of the AssignmentEE308FZ Software EngineeringAssignment RequirementsAssignment 6 - Beta Sprint (Frontend Group Sprint Log)Objectiv…

作者头像 李华
网站建设 2026/4/16 7:35:52

Zotero PDF Translate 插件:解锁多语言PDF阅读新体验

在学术研究和文献阅读过程中&#xff0c;面对大量外文PDF文档时&#xff0c;语言障碍常常成为困扰研究者的难题。Zotero PDF Translate 插件应运而生&#xff0c;为 Zotero 用户提供了一键翻译PDF文档中选中文本的强大功能&#xff0c;让跨语言阅读变得轻松便捷。 【免费下载链…

作者头像 李华
网站建设 2026/4/16 7:35:53

Pix4D Mapper无人机数据处理终极指南:从入门到精通

Pix4D Mapper无人机数据处理终极指南&#xff1a;从入门到精通 【免费下载链接】UAVPix4DMapper介绍与安装包 Pix4D Mapper是一款专业的无人机&#xff08;UAV&#xff09;数据处理软件&#xff0c;广泛应用于地理信息系统&#xff08;GIS&#xff09;、农业、建筑和环境监测等…

作者头像 李华