【问题标题】:What is wrong with clock_gettime with CLOCK_REALTIME?使用 CLOCK_REALTIME 的 clock_gettime 有什么问题?
【发布时间】:2021-10-09 21:24:31
【问题描述】:

考虑以下代码:

struct timespec ts;
uint64_t start_time;
uint64_t stop_time;

if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
    abort();
}
 
start_time = ts.tv_sec * UINT64_C(1000000000) + ts.tv_nsec;
 
/* some computation... */
 
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
    abort();
}
 
stop_time = ts.tv_sec * UINT64_C(1000000000) + ts.tv_nsec;
 
printf("%" PRIu64 "\n", (stop_time - start_time + 500000000) / 1000000000);

在绝大多数情况下,代码按我的预期工作,即打印进行计算的秒数。 然而,很少发生一种异常情况。 该程序报告秒数,如 18446743875、18446743877、18446743962 等。 我认为这个数字大致匹配 264 纳秒(约 584 年)。 所以我怀疑ts.tv_nsec 有时等于-1。

所以我的问题是: 我的代码有什么问题? 添加 264 纳秒的位置和原因是什么?

【问题讨论】:

  • 您的操作系统是什么,包括版本?您的系统是否使用 NTP?
  • @AndrewHenle uname -srvmo 给了Linux 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u2 (2019-11-11) x86_64 GNU/Linux。系统使用 NTP。但是,关于NTP,我认为它不可能是584年的跳跃。
  • 根据规范,tv_nsec 的有效值在 [0,999999999] 范围内。不能是 -1。
  • 你可以试试CLOCK_MONOTONIC。见Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?
  • 我认为这不可能是 584 年的跳跃 不,但你可能会得到一个跳跃,导致你减去无符号的 64 位值会回绕

标签: c time real-time-clock gettime


【解决方案1】:

我认为您的代码没有任何问题。我怀疑你的操作系统偶尔会为 CLOCK_REALTIME 提供一个异常值——尽管我很惊讶,我无法想象它可能是什么。

我建议像这样重写你的代码:

struct timespec start_ts, stop_ts;
uint64_t start_time;
uint64_t stop_time;

if (clock_gettime(CLOCK_REALTIME, &start_ts) != 0) {
    abort();
}
 
start_time = start_ts.tv_sec * UINT64_C(1000000000) + start_ts.tv_nsec;
 
/* some computation... */
 
if (clock_gettime(CLOCK_REALTIME, &stop_ts) != 0) {
    abort();
}
 
stop_time = stop_ts.tv_sec * UINT64_C(1000000000) + stop_ts.tv_nsec;

uint64_t elapsed = (stop_time - start_time + 500000000) / 1000000000;
printf("%" PRIu64 "\n", elapsed);

if(elapsed > 365 * 86400 * UINT64_C(1000000000)) {
    printf("ANOMALY:\n");
    printf("start_ts = %lu %lu\n", start_ts.tv_sec, start_ts.tv_nsec);
    printf("stop_ts = %lu %lu\n", stop_ts.tv_sec, stop_ts.tv_nsec);
}

然后,如果/当它再次发生时,您将获得更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 2018-12-31
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    相关资源
    最近更新 更多