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

Linux内核6.4中timer.h定时器失效,是否已废弃?该用什么替代?

内核定时器<linux/timer.h>是否废弃?100ms定时写文件的替代方案

<linux/timer.h>并未被废弃

Linux 6.4内核中<linux/timer.h>依然是合法且常用的定时器接口,你的定时器无法正常工作并非因为接口废弃,而是代码中存在其他问题。

你的代码存在的核心问题

  • 未循环调度定时器:当前代码仅在模块初始化时调度了一次定时器,100ms触发回调后就不会再执行。要实现每100ms执行一次,必须在回调函数末尾重新调用mod_timer。
  • 错误的文件写入函数:内核态没有file_write这个函数,需要使用filp_open、vfs_write、filp_close等内核文件操作接口,且操作时必须持有正确的锁、处理权限问题。
  • 未初始化变量:freq_sec和filepath两个全局变量未赋值,直接在printk中使用会导致未定义行为。
  • 缺少模块退出清理:没有定义__exit函数来删除定时器,模块卸载时会引发资源泄漏。

修正后的代码示例

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/uaccess.h>
#include <linux/slab.h>

static unsigned int interval_ms = 100;
static const char *filepath = "/tmp/kernel_test.log"; // 初始化文件路径
static struct timer_list my_timer;

static void timer_callback(struct timer_list *data) {
    struct file *file;
    loff_t pos = 0;
    const char *msg = "Hello from kernel module\n";
    size_t msg_len = strlen(msg);

    // 打开文件(注意:内核态操作文件需谨慎,避免死锁)
    file = filp_open(filepath, O_WRONLY | O_APPEND | O_CREAT, 0644);
    if (IS_ERR(file)) {
        printk(KERN_ERR "Failed to open file: %ld\n", PTR_ERR(file));
        goto reschedule;
    }

    // 写入内容
    mm_segment_t old_fs = get_fs();
    set_fs(KERNEL_DS);
    ssize_t ret = vfs_write(file, msg, msg_len, &pos);
    set_fs(old_fs);

    if (ret < 0) {
        printk(KERN_ERR "Failed to write to file: %ld\n", ret);
    }

    filp_close(file, NULL);

reschedule:
    // 重新调度定时器,实现循环执行
    mod_timer(&my_timer, jiffies + msecs_to_jiffies(interval_ms));
}

static int __init my_init(void) {
    timer_setup(&my_timer, timer_callback, 0);
    // 第一次调度定时器
    mod_timer(&my_timer, jiffies + msecs_to_jiffies(interval_ms));
    printk(KERN_INFO "Timer module loaded, interval: %ums\n", interval_ms);
    return 0;
}

static void __exit my_exit(void) {
    // 删除定时器,清理资源
    del_timer_sync(&my_timer);
    printk(KERN_INFO "Timer module unloaded\n");
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Kernel timer with file write example");

替代方案:高精度定时器(hrtimer)

如果需要更高精度的定时(比如100ms级别的精确触发),可以使用<linux/hrtimer.h>提供的高精度定时器接口,它适合对定时精度要求更高的场景:

#include <linux/hrtimer.h>
#include <linux/ktime.h>

static struct hrtimer my_hrtimer;
static ktime_t interval;

enum hrtimer_restart hrtimer_callback(struct hrtimer *timer) {
    // 这里写你的文件操作逻辑,和上面类似
    
    // 重新调度定时器
    hrtimer_forward_now(timer, interval);
    return HRTIMER_RESTART;
}

static int __init my_init(void) {
    interval = ktime_set(0, 100 * 1000 * 1000); // 100ms
    hrtimer_init(&my_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    my_hrtimer.function = hrtimer_callback;
    hrtimer_start(&my_hrtimer, interval, HRTIMER_MODE_REL);
    return 0;
}

static void __exit my_exit(void) {
    hrtimer_cancel(&my_hrtimer);
}

注意事项

  • 内核态操作文件存在风险,可能引发死锁(比如在持有内核锁时操作文件),尽量避免在生产环境中频繁执行此类操作。
  • 所有内核模块必须遵循GPL协议(如果使用非GPL接口需要特殊处理),否则无法加载。

内容的提问来源于stack exchange,提问作者Artshellorok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:52:36