【问题标题】:Why is the time reported by time() sometimes 1 second behind the seconds component of timespec_get() in C code?为什么 time() 报告的时间有时比 C 代码中 timespec_get() 的秒组件慢 1 秒?
【发布时间】:2020-01-17 13:58:38
【问题描述】:

以下sn-p的代码:

struct timespec ts;
for (int x = 0; x < 100000000; x++) {
    timespec_get(&ts, TIME_UTC);
    long cTime = (long) time(NULL);
    if (cTime != ts.tv_sec && ts.tv_nsec < 3000000) {
        printf("cTime: %ld\n", cTime);
        printf("ts.tv_sec: %ld\n", ts.tv_sec);
        printf("ts.tv_nsec: %ld\n", ts.tv_nsec);
    }
}

产生这个输出:

...
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2527419
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2534036
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2540359
cTime: 1579268059
ts.tv_sec: 1579268060
ts.tv_nsec: 2547039
...

为什么cTimets.tv_sec 之间存在差异?请注意,如果条件更改为ts.tv_nsec &gt;= 3000000,则不会出现此问题。该问题依赖于小于 3000000 的纳秒。

【问题讨论】:

  • 您需要更具体地了解所使用的操作系统、操作系统版本、使用的 C 库版本。
  • @Someprogrammerdude Linux Debian 8,GCC 6.3.0。
  • timespec_get() 是什么?这是 C 还是 C++?看起来像std::timespec_get。请使用适当的标签。
  • @MarcoBonelli:它是在 C11 中添加到 C 中的。 Can reproduce online.
  • @ShadowRanger 谢谢你的参考,我在我的系统上看不到timespec_getman 条目,所以我匆忙下结论。有道理。

标签: c time posix timespec


【解决方案1】:

原因是,您(隐式)使用不同的系统时钟。 timespec_get() 使用高分辨率 系统范围的实时时钟,而time() 使用粗略 实时时钟。

尝试使用

clock_gettime(CLOCK_REALTIME_COARSE, &ts);

而不是你的timespec_get(),那么差异应该会消失。

编辑:

这可以在Linux Kernel Source, vclock_gettime.c看到

确实,这里的问题有点微妙。 CLOCK_REALTIME_COARSECLOCK_REALTIME 使用的结构成员的 seconds-part 包含相同的值,但 nanoseconds-part 不同;对于CLOCK_REALTIME,它可以大于1000000000(即一秒)。在这种情况下,它在调用时被修复:

ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
ts->tv_nsec = ns;

此更正既不会使用 CLOCK_REALTIME_COARSE 执行,也不会使用 time()。这解释了CLOCK_REALTIMEtime() 之间的区别。

【讨论】:

  • 这是否记录在任何地方,或者只是 time 的一个工件,使用(可能)更高性能但不太准确的时钟实现(理论上它无论如何只有第二个粒度,所以谁需要精度)?当您只要求第二个粒度时,我认为实时滞后一毫秒左右(在线测试显示偶尔滞后超过一毫秒,但不会超过)并不是那么重要。
  • @ShadowRanger 我添加了更多细节
  • 没有明确的意图文档,但这对于投票来说已经足够详细了。 :-) 有趣的是,时钟实际上可以报告超过一秒的额外纳秒。
  • @ShadowRanger 除了来源之外,我找不到真正的文档,这也意味着,行为也可能在没有事先通知的情况下发生详细变化
  • @Ctx 感谢您的详细解答!我将使用您建议的 timespec_get() 而不是 clock_gettime(),因为 timespec_get() 是 C11 而不是 POSIX,并且不需要设置要使用的时钟。我不知道使用了不同的时钟,但考虑到选择,我认为使用粗时钟没有多大意义。
猜你喜欢
  • 1970-01-01
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多