Linux 内核 4.18 中的 mod_timer 函数存在问题。始终存在 10% 左右的漂移,这会导致驱动程序出现同步问题。下面附有 100ms 定时器的示例内核模块以及始终延迟 10ms 的相应输出。 CONFIG_HZ设置为100,不同HW结果一致。
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/gpio.h>
MODULE_LICENSE("GPL");
void simple_timer_function(struct timer_list *);
struct timer_list simple_timer;
struct timespec64 ts;
static int __init simple_timer_module_init (void)
{
timer_setup(&simple_timer,simple_timer_function,0);
mod_timer(&simple_timer, jiffies + msecs_to_jiffies(100));
printk(KERN_INFO" simple_timer_module_init init %ld\n",jiffies);
return 0;
}
void simple_timer_function(struct timer_list *timer)
{
printk(KERN_INFO" simple_timer_function Entry %d ms %ld \n",jiffies_to_msecs(jiffies),jiffies);
ktime_get_ts64(&ts);
printk(KERN_INFO" Timerfunction %llu.%09u seconds\n",(u64)ts.tv_sec, (u32)ts.tv_nsec);
mod_timer(&simple_timer, (jiffies + msecs_to_jiffies(100)));
}
static void __exit simple_timer_module_exit (void)
{
del_timer(&simple_timer);
}
module_init(simple_timer_module_init);
module_exit(simple_timer_module_exit);
输出:
simple_timer_function Entry 64206210 ms 4301387917
Timerfunction 64506.210291016 seconds
simple_timer_function Entry 64206320 ms 4301387928
Timerfunction 64506.320284514 seconds
simple_timer_function Entry 64206430 ms 4301387939
Timerfunction 64506.430298059 seconds
simple_timer_function Entry 64206540 ms 4301387950
Timerfunction 64506.540331204 seconds
simple_timer_function Entry 64206650 ms 4301387961
Timerfunction 64506.650281875 seconds
simple_timer_function Entry 64206760 ms 4301387972
Timerfunction 64506.760230434 seconds
simple_timer_function Entry 64206870 ms 4301387983
Timerfunction 64506.870294392 seconds
simple_timer_function Entry 64206980 ms 4301387994
Timerfunction 64506.980259710 seconds
simple_timer_function Entry 64207090 ms 4301388005
Timerfunction 64507.090272193 seconds
simple_timer_function Entry 64207200 ms 4301388016
知道如何解决吗?
在大多数内核源代码中,“mod_timer”都是通过 mod_timer(&timer_func, jiffies + DELAY) 调用的,因此这些延迟是否存在漂移。 我在 Linux 内核中读到了类似的答案:Why add_timer() is修改我的“expires”值?.