Linux/c++ 定时方法,尽管有漂移,但每 N 秒执行一次

Linux/c++ timing method to gaurentee execution every N seconds despite drift?

本文关键字:执行 一次 但每 漂移 定时 c++ 方法 Linux      更新时间:2023-10-16

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

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

意识到,由于在操作系统上运行的本质,任何计时器的执行都会有一定的不一致/延迟,以至于我无法确定我将在 x 秒内执行。 但是只要它保持较小的正态分布,这很好,我不希望漂移让时间持续变得越来越远。

我也希望尽可能降低轮询的 CPU 成本,但这是次要问题。

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

谢谢。

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

clock_gettime和clock_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 */
}

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

其他睡眠方法,例如 nanosleep 和 select,只允许指定时间间隔并使用 CLOCK_REALTIME ,这是系统时间,可能会发生变化。

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

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

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

这样,您

就不会将每个可能具有巨大漂移的即时报价添加到计数器中,而是绝对计算自开始以来的时间,因此您知道执行的确切时间。