【问题标题】:Linux/c++ timing method to gaurentee execution every N seconds despite drift?Linux/c++ 计时方法每 N 秒执行一次,尽管有漂移?
【发布时间】:2012-06-22 16:49:12
【问题描述】:

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

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

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

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

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

谢谢。

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

【问题讨论】:

  • 你的硬件平台是什么?您是否打算为您的应用程序使用实时内核和实时调度?
  • 另外,您对boost 的“分发麻烦”有何期待?如果您静态链接到它,则无需部署/分发任何内容。
  • 我没有实时运行。常规的 redhawk linux(可能)。我不需要实时的精确度,只是为了避免漂移。
  • 提升的麻烦是由于我的雇主没有提升自己。毕竟,好的公司喜欢用愚蠢的限制来阻碍那里的员工!
  • @dsollen:PC 的内部时钟会漂移。您需要使用原子钟查询网络时间源。

标签: c++ linux time drift


【解决方案1】:

我会记录我开始时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,所以你执行。

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

【讨论】:

  • 更好的是,计算下一次运行的时间,并使用睡眠功能(select 或类似的便携式亚秒级sleep)。但关键是使用当前时间和上次预定时间后的 5 秒,而不是当前时间的 5 秒。
  • 时间只有一秒的感知,不是吗?这将允许至少一秒钟的差异,不是吗?另外,这是否意味着我每次都需要进行系统调用,还是 C 会抽象出对系统调用的需求?
  • select 给予亚秒级睡眠。
  • gettimeofday 使用struct timeval,它具有微秒,就像select 需要的一样。另一方面,pselect 需要 struct timespec 和纳秒。
【解决方案2】:

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,只允许指定时间间隔,使用CLOCK_REALTIME,这是系统时间,可能会发生变化。

【讨论】:

  • 据此:stuff.onse.fi/man?program=clock_gettime&section=3CLOCK_MONOTONIC_RAW 是需要用来避免由于 NTP 等导致时间变化的。
  • 这是一个很好的答案。一个后续问题。我实际上可能希望在闰秒事件中尽早打印,这样时间对于那些阅读文件的人来说似乎是连续的(仍在尝试在工作中获得对此的反馈)。我想如果需要的话,我可以通过使用不同的常量传递给时钟方法来做到这一点?
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    • 2019-09-27
    • 1970-01-01
    相关资源
    最近更新 更多