Hrtimer的回调函数delay

Hrtimer的回调函数delay,delay,Delay,我写了一个linux模块,它启动一个hrtimer,它的回调函数每20us调用一次。假设开始时间是0,那么回调函数的执行时间应该是20us,40us,60us,…,但是在我的程序中,结果是在某些情况下,回调函数的执行可能会延迟很长时间。我想知道为什么会这样 我的模块在x86_64平台上运行,tsc用于计算延迟。以下是我的代码: static enum hrtimer\u restart hwt\u timer\u fn(struct hrtimer*timer){ 无符号长勾号开始; rdtsc

我写了一个linux模块,它启动一个hrtimer,它的回调函数每20us调用一次。假设开始时间是0,那么回调函数的执行时间应该是20us,40us,60us,…,但是在我的程序中,结果是在某些情况下,回调函数的执行可能会延迟很长时间。我想知道为什么会这样

我的模块在x86_64平台上运行,tsc用于计算延迟。以下是我的代码:

static enum hrtimer\u restart hwt\u timer\u fn(struct hrtimer*timer){
无符号长勾号开始;
rdtscll(勾选开始);
勾选错误=勾选开始-cmp循环;
cmp\u cycle+=tick\u cycle;//cmp\u cycle表示回调函数的下一次执行时间
hrtimer\u add\u expires(计时器,expires);
计数++;
如果(勾选错误>最大错误)
最大错误=勾选错误;
如果(勾选错误<最小错误)
最小错误=勾选错误;
返回HRU重新启动;
}
静态int-kthread_计时器(void*arg){
结构timespec val;
无符号长勾号开始;
val.tv_sec=0;
val.tv_nsec=20*1000;
expires=timespec_到_ktime(val);
计数=0;
最大错误=最小错误=0;
tick_cycle=cpu_khz/50;//tsc周期为20us
printk(“cpu频率:%u,滴答周期:%llu\n”,cpu频率khz,滴答周期);
hrtimer\u init(计时器、时钟实时、hrtimer\u模式\u ABS);
timer.function=hwt\u timer\u fn;
rdtscll(勾选开始);
hrtimer\u启动(&timer,expires,hrtimer\u MODE\u REL);
cmp_循环=勾选开始+勾选循环;
返回0;
}
int hwt_定时器_初始化(无效){
cpumask_t面罩;
CPU_清除(屏蔽);
cpu_设置(0,掩码);
thread=kthread_create(kthread_hrtimer,NULL,“kthread_hrtimer”);
如果(是错误(线程))
{
printk(“创建失败\n”);
返回1;
}
设置\u CPU \u允许\u ptr(线程和掩码);
唤醒进程(线程);
返回0;
}
无效hwt_定时器_退出(无效){
而(hrtimer\u尝试\u取消(&timer)<0);
printk(“最大错误:%lld,最小错误:%lld\n”,最大错误,最小错误);
printk(“计数:%lld\n”,计数);
printk(“\n\n”);
}

首先,Linux不是硬实时操作系统。虽然hrtimer保证在其设定目标结束后而不是之前触发,但响应时间没有保证界限。具体而言,hrtimers机制不保证目标时间发生与计时器启动之间经过的时间量

触发延迟的一个可能原因是内核可能处于涉及禁用中断的关键部分。在这种情况下,将导致调用hrtimer函数的计时中断被屏蔽,直到内核退出临界区并再次启用中断

为了解决单边定时器保证的第一个问题,我建议如下:

  • 使用一个阈值,让我们称之为计时器\u阈值

  • 为目标时间设置计时器时,请稍早设置实际目标。 (例如,使用“expires-(TIMER\u THRESHOLD/2)”而不是使用“expires”)

  • 在计时器回调内,对照“目标时间”检查“当前时间”,并假设如果“当前时间”在目标时间的计时器_阈值内,则已达到目标时间

另外,对于定期定时事件,我建议现在使用hrtimer\u forward\u,而不是hrtimer\u add\u expires。原因是要处理计时器错过其截止日期超过计时器周期的情况。在这种情况下,hrtimer\u add\u expires仍然设置了一个过去的目标


最后,我的另一个建议是,如果可能的话,使用比20美元更长的延迟时间。20美元是很短的一段时间。在GHz处理器上,大约有20000条指令。

我支持萨法耶·艾哈迈德的答案。无论如何,我想添加一些评论

检查系统上的CONFIG_HZ选项,通常CONFIG_HZ为1000。这意味着系统计时器精度可以在1ms左右(通常优于1ms,但不能达到“us”精度)

尝试将CONFIG_HZ更改为更大的值,以检查您的hrtimer精度是否有所提高。如果没有,请检查hrtimer API。可能问题与您误用hrtimer API有关