运行定时写文件的Linux内核模块时系统崩溃无法启动求助
Linux内核模块定时写文件导致系统崩溃的问题分析与修复
问题根源分析
你的内核模块存在多个致命问题,直接触发系统崩溃:
软中断上下文执行阻塞操作
定时器回调函数timer_rest运行在软中断上下文,该上下文禁止调用任何可能引发睡眠/阻塞的函数(如filp_open、kernel_write、filp_close)。文件IO操作通常需要等待磁盘响应、获取锁,这些操作都会触发睡眠,在软中断上下文执行会破坏内核调度逻辑,引发死锁或直接崩溃。未检查内核函数返回值
filp_open可能因权限不足、路径不存在等原因返回错误指针(如ERR_PTR(-ENOENT)),但你的代码直接用返回值调用后续操作,操作无效指针会触发内核Oops,直接导致系统崩溃。字符串宏定义错误
TEXT宏定义中的换行未使用转义符\n,而是直接换行,导致宏定义不完整,buff数组初始化出错,后续strlen(buff)可能读取到内存垃圾数据,引发越界访问。全局变量管理不当
offset作为全局变量,未考虑文件被外部修改的情况;i_fp未初始化,若filp_open失败,filp_close操作错误指针会加剧问题。
修复后的代码
我们用工作队列处理文件操作(工作队列运行在进程上下文,允许阻塞),同时修复所有错误:
#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/kernel.h> #include <linux/timer.h> #include <linux/workqueue.h> MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Fixed periodic file writing kernel module"); #define TEXT "Hello from kernel mod\n" #define FILE_PATH "/home/hajol/Test.txt" static int g_timer_interval = 10000; // 10秒间隔 static struct timer_list g_timer; static struct work_struct g_write_work; // 工作队列回调:执行文件写入(进程上下文,允许阻塞) static void do_file_write(struct work_struct *work) { struct file *fp; loff_t offset = 0; ssize_t ret; // 打开文件,使用O_APPEND自动追加到末尾,无需手动管理offset fp = filp_open(FILE_PATH, O_RDWR | O_CREAT | O_APPEND, 0644); if (IS_ERR(fp)) { pr_err("Failed to open file: %ld\n", PTR_ERR(fp)); return; } // 写入内容 ret = kernel_write(fp, TEXT, strlen(TEXT), &offset); if (ret < 0) { pr_err("Failed to write to file: %ld\n", ret); } else { pr_info("Wrote %zd bytes to file\n", ret); } // 关闭文件 filp_close(fp, NULL); } // 定时器回调:触发工作队列(软中断上下文,只做非阻塞操作) static void timer_callback(struct timer_list *timer) { // 重新设置定时器 mod_timer(&g_timer, jiffies + msecs_to_jiffies(g_timer_interval)); // 提交工作到系统默认工作队列 schedule_work(&g_write_work); } static int __init kernel_init(void) { // 初始化工作队列 INIT_WORK(&g_write_work, do_file_write); // 初始化定时器 timer_setup(&g_timer, timer_callback, 0); // 启动定时器 mod_timer(&g_timer, jiffies + msecs_to_jiffies(g_timer_interval)); pr_info("Periodic file writer module loaded\n"); return 0; } static void __exit kernel_exit(void) { // 删除定时器,确保已停止 del_timer_sync(&g_timer); // 等待剩余工作完成,避免资源泄漏 flush_scheduled_work(); pr_info("Periodic file writer module unloaded\n"); } module_init(kernel_init); module_exit(kernel_exit);
关键修复点说明
- 用工作队列隔离阻塞操作:定时器仅负责触发工作,实际文件IO由工作队列在进程上下文执行,规避软中断上下文的限制。
- 添加错误检查:对
filp_open、kernel_write的返回值进行校验,出错时打印日志而非直接崩溃。 - 修正字符串宏:用
\n正确表示换行,避免数组初始化错误。 - 使用O_APPEND:打开文件时添加
O_APPEND标志,自动将写入位置定位到文件末尾,无需手动管理offset。 - 安全清理资源:模块卸载时用
del_timer_sync确保定时器停止,flush_scheduled_work等待剩余工作完成,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Hajol
相关产品推荐
相关产品推荐

