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
相关产品推荐
相关产品推荐

