3

我有一个程序需要每 X 秒执行一次以写入一些输出。该程序将在每个输出之间进行一些间歇性轮询和处理。因此,例如,我可能每 5 秒输出一次,但我每 0.1 秒醒来一次轮询一次,直到达到下一个 5 秒标记。理论上,该程序将在重新启动之间运行数月,甚至可能更长。

我需要每 X 秒执行一次,以保持与挂钟一致。换句话说,我不能让时钟漂移导致我偏离 X 秒标记。在间歇轮询中,我不需要完全相同级别的准确度,但我想更频繁地轮询一秒钟,所以我需要一个可以表示亚秒级精度的结构。

我意识到,由于在操作系统上运行的本质,任何计时器的执行都会存在一定的不一致/延迟,因此我无法保证我将在每x 秒内执行一次但这很好,只要它保持一个小的正态分布,我不想要的是漂移让时间不断地越来越远。

我还希望尽量减少轮询的 CPU 成本,但这是次要问题。

有哪些可用于 Linux 的时序结构可以最好地为我提供这种级别的精确度?由于分发的麻烦,我试图避免在应用程序中包含提升,但如果必须的话可以使用它。所以首选使用标准 c++ 库的方法,但如果 Bosst 可以做得更好,我也想知道这一点。

谢谢你。

-ps,我不能使用 c++11。这不是一个选项,所以我无法使用它的任何构造。

4

3 回答 3

4

clock_gettimeclock_nanosleep都在亚秒级时间运行,使用CLOCK_MONOTONIC应该防止由于调整系统时间(例如 NTP 或adjtimex)而导致的任何偏差。例如,

long delay_ns = 250000000;
struct timespec next;
clock_gettime(CLOCK_MONOTONIC, &next);
while (1) {
    next.ts_nsec += delay_ns;
    next.ts_sec += ts_nsec / 1000000000;
    next.ts_nsec %= 1000000000;
    clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
    /* do something after the wait */
}

实际上,您应该检查您是否由于信号而提前返回,以及您是否应该跳过一个间隔,因为您在睡觉时经过了太多时间。

其他睡眠方法,例如nanosleepselect,仅允许指定时间间隔和 use CLOCK_REALTIME,这是系统时间并且可能会更改。

于 2012-06-20T14:41:32.947 回答
1

如果您需要一些没有抖动或时钟漂移的精确计时,请确保有一个外部时间源,如 GPS、原子钟或无线电时钟。例如,参见此PDF中记录的 NTP 集成。所有 NTP 技巧在 Linux 和 NanoBSD(在 PDF 中)上都能正常工作。

于 2012-06-21T10:33:24.520 回答
0

我会记录t_0我开始的时间,然后在任何给定时间t,如果i = (t - t_0)/X(整数除法)大于上次执行的相同数量,则再次执行。

例如,假设您每 5 秒跑步一次,如果您从 23 点开始,则记录i = 0, t_0 = 23. 然后在时间 27, (27 - 23)/5 = 0,所以你还没有执行。但是下一次遇到(28 - 23)/5 = 1大于 0 的时间 28,所以你执行。

这样,您就不会在每个可能产生巨大漂移的滴答声中添加到计数器,您绝对计算自开始以来的时间,因此您知道执行的确切时间。

于 2012-06-20T14:18:28.633 回答