为什么用time()报告的时间有时比C代码中的timespec_get()的秒部分晚1秒?


12

以下代码段:

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
...

cTime和之间为什么存在差异ts.tv_sec?请注意,如果将条件更改为,则不会发生此问题ts.tv_nsec >= 3000000。该问题取决于小于3000000的纳秒。


您需要更详细地说明所使用的操作系统,版本,所用C库的版本。
一些程序员哥们

2
@Someprogrammerdude Linux Debian 8,GCC 6.3.0。
Theo d'Or

什么timespec_get()啊 这是C还是C ++?看起来像std::timespec_get。请使用适当的标签。
Marco Bonelli

@MarcoBonelli:它已添加到C11中的C中。可以在线复制
ShadowRanger

@ShadowRanger感谢您的参考,我在系统上看不到该man条目,timespec_get因此我下结论了。说得通。
Marco Bonelli

Answers:


11

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

尝试使用

clock_gettime(CLOCK_REALTIME_COARSE, &ts);

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

编辑:

可以在Linux内核源代码vclock_gettime.c中看到

确实,在这里看到这个问题有些微妙。CLOCK_REALTIME_COARSE和使用的结构成员的秒部分CLOCK_REALTIME包含相同的值,但纳秒部分不同;用CLOCK_REALTIME它可以大于1000000000(这是一秒)。在这种情况下,它已固定在通话中:

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

既不使用CLOCK_REALTIME_COARSE也不使用进行此校正time()。这解释了CLOCK_REALTIME和之间的区别time()


是否在任何地方都记录了此文档,或者只是time用(可能是)性能更高但时钟精度较低的方式实现的工件(从理论上讲,它只有第二粒度,所以谁需要精度)?当您仅要求第二个粒度时,将实时滞后一毫秒左右(在线测试显示偶尔会延迟一毫秒以上,但不会超过几毫秒)并不是那么重要。
ShadowRanger

@ShadowRanger我添加了更多详细信息
Ctx

没有明确的意图文档,但这足够详细。:-)有趣的是,时钟实际上可以报告超过一秒的额外纳秒值。
ShadowRanger

@ShadowRanger除了该源以外,我找不到真正的文档,这也意味着该行为也可能在没有事先通知的情况下进行详细更改
Ctx

@Ctx谢谢您的详细回答!我将使用timespec_get()而不是您建议的clock_gettime(),因为timespec_get()是C11而不是POSIX,并且不需要设置要使用的时钟。我不知道使用了不同的时钟,但是给出选择后,我认为使用粗时钟没有太大意义。
西奥多尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.