Jos*_*ley 21 c linux time gettimeofday
在我测试的两个系统上(一个32位的Ubuntu 12.04服务器和一个64位的Ubuntu 13.10 VM),time()给出的纪元以来的秒数可能与gettimeofday()不同.
具体来说,虽然我在调用time() 后调用gettimeofday(),但返回的值time()有时小于tv_sec返回的值gettimeofday().
这显然发生在时钟滚动到新的秒钟之后.
这导致了我的一些代码中的错误,这些代码期望time()和gettimeofday()的秒可以互换.
示例代码演示此问题:
#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\n", same);
printf("Different: %i\n", different);
printf("Largest difference seen at %i\n", max_usec);
}
Run Code Online (Sandbox Code Playgroud)
请注意,我调用time()第二个,只是抱怨它的值小于 gettimeofday()的值.
样本输出:
Same: 33282836
Different: 177076
Largest difference seen at 5844
Run Code Online (Sandbox Code Playgroud)
即,两个值相同的是3300万次,它们相差177k次,并且它们在新的秒的5844微秒内始终不同.
这是一个已知的问题?是什么导致这个?
aki*_*ira 21
这两个调用都是作为内核系统调用实现的.两个函数最终都读取a struct timekeeper,两者都指向同一个实例.但他们在做什么方面有所不同:
使用get_seconds()函数,这是一个快捷方式:
struct timekeeper *tk = &timekeeper;
return tk->xtime_sec;
Run Code Online (Sandbox Code Playgroud)
它只是回来了xktime_sec.
gettimeofday():gettimeofday()另一方面,使用do_gettimeofday()(via getnstimeofday)读取字段xktime_sec以及xktime_nsec(via timekeeping_get_ns).在这里可能会发生xktime_nsec比纳秒更多的纳秒.这个潜在的额外时间用于tv_sec通过调用timespec_add_ns()执行此操作的函数来增加字段:
a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
a->tv_nsec = ns;
Run Code Online (Sandbox Code Playgroud)
所以,tv_sec可能比xktime_sec领域更大.而且你有它:time()给你什么以及什么gettimeofday()给你带来什么不同.
我今天在fluxbox中反对这个问题,直到找到一个更好的解决方案我接受这个:
uint64_t t_usec = gettimeofday_in_usecs(); // calcs usecs since epoch
time_t t = static_cast<time_t>(t_usec / 1000000L);
Run Code Online (Sandbox Code Playgroud)
双方time并gettimeofday实现为所谓的Linux vsyscalls.意味着您的代码将被重定向到内核所拥有的,但是包含仅定期更新的结果的用户空间映射页面.
在Ubuntu中(我没有在RedHat Linux中观察到这种行为),值的值gettimeofday在值之前更新,time因此可能会得到不一致的值:
内核更新
gettimeofday你查询
gettimeofday你查询
time内核更新
time
交换你的电话会产生一致的结果:
t = time(NULL);
gettimeofday(&tv, NULL);
if (t > tv.tv_sec) { ...
Run Code Online (Sandbox Code Playgroud)
这种行为是由于在 Linux 内核中实现了计时。
Linux 维护一个跟踪当前挂钟时间的变量;这保持在纳秒精度并定期更新。(它是tk_core.timekeeper.{xtime_secs, tkr_mono.xtime_nsec}在最近的内核版本中。)
time()调用get_seconds(),它只返回此变量的秒部分 - 因此,根据挂钟时间更新的时间,可能会返回一个稍微过时的值。
gettimeofday()不仅读取挂钟变量的最新值,而且(通过timekeeping_get_ns())从硬件时钟(通常是x86 系统中的TSC,尽管这可以在运行时配置)进行新的读取并应用更正。
由于该校正计算, 返回的结果有可能gettimeofday()滚动到下一秒,因此返回tv_sec比 的结果更高的值time()。
| 归档时间: |
|
| 查看次数: |
10297 次 |
| 最近记录: |