Почему время, сообщаемое функцией time (), иногда составляет 1 секунду после секундного компонента timespec_get () в коде C? - PullRequest
12 голосов
/ 17 января 2020

Следующий фрагмент кода:

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.

1 Ответ

11 голосов
/ 17 января 2020

Причина в том, что вы (неявно) используете разные системные часы. timespec_get() использует системные часы реального времени высокого разрешения, а time() использует грубые часы реального времени.

Попробуйте использовать

clock_gettime(CLOCK_REALTIME_COARSE, &ts);

вместо вашего timespec_get(), тогда разница должна исчезнуть sh.

Редактировать:

Это можно увидеть в Linux Kernel Source, 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().

...