Linux中间隔定时器的精度是多less?

我正在试图描述Linux上的定时器抖动。 我的任务是运行100毫秒定时器,看看数字是如何工作的。

我正在研究多核机器。 我使用了setitimer()的标准用户程序,和root一样运行,然后是处理器关联,最后是处理器关联和进程优先级。 然后,我运行与PREEMPT_RT内核相同的程序,然后使用clock_nanosleep()运行示例,如PREEMPT_RT页面上的演示代码所示。 在所有的运行中,计时器的性能非常相似,尽pipe发生了变化,但并没有真正的区别。

我们的最终目标是稳定的计时器。 我能定期得到的最坏的情况是大约200us。 所有情况下的直方图显示了非常奇怪的行为。 首先,我不希望定时器提前开火。 但他们呢。 正如你可以在直方图中看到的那样,我会在0偏移的任一侧获得低谷。 这些在第二个图中显示为三个带。 在第一个图中,X轴以微秒为单位。 在第二个图中,Y轴以微秒为单位。

我跑了30次testing(也就是300个定时器事件)100次来产生一些数字。 你可以在下面的图表中看到它们。 200us有很大的下降。 所有30000个计时器事件时钟偏移量都绘制在第二个graphics中,您可以看到一些exception值。

X轴以微秒为单位Y轴以微秒为单位

所以问题是,有没有其他人做过这种分析? 你有没有看到同样的行为? 我的假设是RT内核在负载很重的系统上有帮助,但在我们的情况下,它并不能帮助消除定时器的抖动。 这是你的经验吗?

这是代码。 就像我以前说过的那样,我修改了使用clock_nanosleep()函数的PREEMPT_RT站点上的示例代码,所以我将不会包含对此的最小更改。

#include <signal.h> #include <stdio.h> #include <string.h> #include <sys/time.h> #include <stdlib.h> #define US_PER_SEC 1000000 #define WAIT_TIME 100000 #define MAX_COUNTER 300 int counter = 0; long long last_time = 0; static long long times[MAX_COUNTER]; int i = 0; struct sigaction sa; void timer_handler(int signum) { if (counter > MAX_COUNTER) { sigaction(SIGALRM, &sa, NULL); for (i = 0; i < MAX_COUNTER; i++) { printf("%ld\n", times[i]); } exit(EXIT_SUCCESS); } struct timeval t; gettimeofday(&t, NULL); long long elapsed = (t.tv_sec * US_PER_SEC + t.tv_usec); if (last_time != 0) { times[counter] = elapsed - last_time; ++counter; } last_time = elapsed; } int main() { struct itimerval timer; memset(&sa, 0, sizeof(sa)); sa.sa_handler = &timer_handler; sigaction(SIGALRM, &sa, NULL); timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 1; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = WAIT_TIME; setitimer(ITIMER_REAL, &timer, NULL); while (1) { sleep(1); } } 

编辑:这是在至强E31220L,运行在2.2 GHz,运行x86_64 Fedora Core 19。

你是对的,不要期望定时器提前开火 – 而不是。 明显的早期触发是因为您没有测量自上次计时器过期以来的时间 – 您正在测量自上一次gettimeofday()调用以来的时间。 如果计时器到期和实际计划进程之间存在延迟,那么您将看到这个gettimeofday()延迟运行, 而下一个提前运行的时间相同

不要记录随后的gettimeofday()调用之间的差异,请尝试记录返回的绝对时间,然后将返回的时间与初始时间之后的N * 100ms进行比较。

如果您希望PREEMPT_RT帮助您,则需要为您的测试程序( SCHED_FIFOSCHED_RR )设置一个实时调度程序策略,该策略需要root权限。