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

使用mod_timer设置10ms定时器却触发20ms的问题排查

内核定时器设置10ms间隔却触发20ms的问题分析与解决

我尝试使用mod_timer设置10毫秒的定时器,但实际触发间隔始终为20毫秒,相关代码、输出及环境如下:

测试代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/unistd.h>
#include <linux/delay.h>

static struct timer_list my_timer;

void my_timer_callback(struct timer_list *timer)
{
    printk("my_timer_callback called (%lu).\n", jiffies);

    mod_timer(&my_timer, jiffies + msecs_to_jiffies(10));
}

static int __init my_init(void)
{
    printk("Timer module loaded\n");

    timer_setup(&my_timer, my_timer_callback, 0);

    mod_timer(&my_timer, jiffies + msecs_to_jiffies(10));

    return 0;
}

static void __exit my_exit(void)
{
    printk("Timer module unloaded\n");

    del_timer(&my_timer);
}

module_init(my_init);
module_exit(my_exit);

MODULE_AUTHOR("developer@kk.com");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);

dmesg输出

[   70.391971] my_timer_callback called (4294944328).
[   70.411947] my_timer_callback called (4294944330).
[   70.431944] my_timer_callback called (4294944332).
[   70.451961] my_timer_callback called (4294944334).

环境信息

  • 内核版本:5.10
  • 内核配置:CONFIG_HZ=100

问题原因

  1. 内核节拍粒度限制:CONFIG_HZ=100表示系统时钟节拍频率为100Hz,每个jiffy(内核节拍单位)对应10ms。msecs_to_jiffies(10)会被转换为1个jiffy,这是传统定时器能支持的最小间隔。
  2. 超时时间被内核调整:当定时器回调函数执行时,当前的jiffies可能已经超出了jiffies + 1的时间点(比如回调在当前节拍的后期执行),内核会自动将下一次超时时间调整到下一个节拍(即jiffies + 2),最终导致实际触发间隔变为20ms(2个jiffy)。

解决方案

方案1:使用高精度定时器(hrtimer)

高精度定时器不受CONFIG_HZ限制,可提供微秒级精度,适合对定时精度要求高的场景。示例代码框架:

#include <linux/hrtimer.h>

static struct hrtimer my_hrtimer;
static ktime_t interval;

enum hrtimer_restart my_hrtimer_callback(struct hrtimer *timer)
{
    printk("hrtimer callback called\n");
    hrtimer_forward_now(timer, interval);
    return HRTIMER_RESTART;
}

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

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

方案2:调整内核CONFIG_HZ值

将CONFIG_HZ设置为更高的值(如250对应4ms间隔、1000对应1ms间隔),可减小jiffy粒度,提升传统定时器的精度。但此操作需要重新编译内核,且会增加系统的时钟中断开销。

方案3:优化传统定时器的超时设置

使用round_jiffies_up()函数确保超时时间对齐到下一个完整的节拍,避免内核将超时时间向后调整:

mod_timer(&my_timer, round_jiffies_up(jiffies + msecs_to_jiffies(10)));

注意:此方法仅能在CONFIG_HZ允许的粒度内优化,无法突破10ms的最小间隔限制。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 07:32:13