You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行定时写文件的Linux内核模块时系统崩溃无法启动求助

Linux内核模块定时写文件导致系统崩溃的问题分析与修复

问题根源分析

你的内核模块存在多个致命问题,直接触发系统崩溃:

  1. 软中断上下文执行阻塞操作
    定时器回调函数timer_rest运行在软中断上下文,该上下文禁止调用任何可能引发睡眠/阻塞的函数(如filp_open、kernel_write、filp_close)。文件IO操作通常需要等待磁盘响应、获取锁,这些操作都会触发睡眠,在软中断上下文执行会破坏内核调度逻辑,引发死锁或直接崩溃。

  2. 未检查内核函数返回值
    filp_open可能因权限不足、路径不存在等原因返回错误指针(如ERR_PTR(-ENOENT)),但你的代码直接用返回值调用后续操作,操作无效指针会触发内核Oops,直接导致系统崩溃。

  3. 字符串宏定义错误
    TEXT宏定义中的换行未使用转义符\n,而是直接换行,导致宏定义不完整,buff数组初始化出错,后续strlen(buff)可能读取到内存垃圾数据,引发越界访问。

  4. 全局变量管理不当
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 21:25:20