time() and gettimeofday() return different seconds
在我测试过的两个系统上(一台32位Ubuntu 12.04服务器和一台64位Ubuntu 13.10 VM),自time()给出纪元以来的秒数可能不同于gettimeofday()的秒数。
具体来说,尽管我在调用
这显然是在时钟翻转到新的秒之后发生的。
这导致我的某些代码中的错误,它们期望time()和gettimeofday()的秒数可以互换。
演示此问题的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include <stdio.h> #include <time.h> #include <sys/time.h> int main() { time_t start = time(NULL); int same = 0; int different = 0; int max_usec = 0; while (1) { time_t t; struct timeval tv; gettimeofday(&tv, NULL); t = time(NULL); if (t < tv.tv_sec) { different++; if (tv.tv_usec > max_usec) { max_usec = tv.tv_usec; } } else { same++; } if (t > start + 5) { break; } } printf("Same: %i ", same); printf("Different: %i ", different); printf("Largest difference seen at %i ", max_usec); } |
请注意,我第二次调用time(),并且仅在其值小于gettimeofday()的情况下才抱怨。
样本输出:
1 2 3 | Same: 33282836 Different: 177076 Largest difference seen at 5844 |
即,这两个值是相同的3300万次,它们是17.7万次,并且在新秒的5844微秒内始终是不同的。
这是一个已知的问题? 是什么原因造成的?
这两个调用都实现为内核syscall。这两个函数最终都读取一个
时间():
使用
1 2 | struct timekeeper *tk = &timekeeper; return tk->xtime_sec; |
它只是返回
另一方面,
1 2 | a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns); a->tv_nsec = ns; |
因此,
今天,我在fluxbox中与这个问题作斗争,直到出现更好的解决方案,我对此表示赞同:
1 2 | uint64_t t_usec = gettimeofday_in_usecs(); // calcs usecs since epoch time_t t = static_cast<time_t>(t_usec / 1000000L); |
在Ubuntu中(我没有在RedHat Linux中观察到这种行为),
kernel updates
gettimeofday You query
gettimeofday You query
time kernel updates
time
交换您的电话会得到一致的结果:
1 2 3 |
此行为是由于在Linux内核中实现了计时功能。
Linux维护一个变量,该变量跟踪当前的挂钟时间;保持到纳秒精度,并定期更新。 (在最新的内核版本中为
由于进行了此校正计算,