Есть ли способ получить правильный CLOCK_TAI в Linux?

1373
Ashley Yakeley

Моя машина Linux поддерживает CLOCK_TAI, но ее смещение от CLOCK_REALTIMEнеправильно равно нулю (это значение по умолчанию). Есть ли программное обеспечение или другое решение, которое будет поддерживаться CLOCK_TAIкак TAI?

Из ответов здесь и здесь, кажется, ни, ntpdни chronydсделать это.

Я был бы рад установить мои аппаратные часы на TAI для достижения этой цели, при условии, что CLOCK_REALTIMEи gettimeofdayт. Д. Возвращаем время POSIX (по сути, UTC).

7

3 ответа на вопрос

4
Edmund Grimley Evans

Я думаю, что вы хотите clock_gettimeс, CLOCK_TAIчтобы работать должным образом. Я сделал также.

Критическое предложение в указанном ответе: «Обратите внимание, что смещение от CLOCK_REALTIME инициализируется при загрузке до нуля, и ни ntpd, ни chronyd по умолчанию не устанавливают его на правильное значение (в настоящее время 35)».

Это может все еще быть истиной, за исключением того, что смещение теперь составляет 37, но недавний ntpd может, по меньшей мере, быть сконфигурирован для установки смещения. Я сделал следующее на машине openSUSE:

vi /etc/ntp.conf # Add the line: leapfile /var/lib/ntp/etc/ntp.leapseconds update-leap service ntpd restart less /var/log/ntp # Check for errors 

Тогда clock_gettime(CLOCK_TAI, &res)казалось, что работает правильно.

Я думаю, что NTP устанавливает смещение с ntp_adjtimeпомощью MOD_TAI. Поиск по источнику хроники с помощью поиска не grep -P '(ADJ|MOD)_TAI'находит совпадений, поэтому кажется, что хрони еще не имеет этой возможности.

3
dfc

Вы можете использовать libtaiот djb: https://cr.yp.to/libtai.html

Что это?

libtai - это библиотека для хранения и манипулирования датами и временем.

libtai поддерживает две шкалы времени: (1) TAI64, охватывающий несколько сотен миллиардов лет с точностью до 1 секунды; (2) TAI64NA, охватывающий тот же период с точностью до 1 аттосекунды. Обе шкалы определены в терминах TAI, действующего международного стандарта реального времени.

libtai предоставляет внутренний формат для TAI64, struct tai, предназначенный для быстрых манипуляций со временем. Процедуры tai_pack () и tai_unpack () конвертируют между struct tai и переносимым 8-байтовым форматом хранения TAI64. libtai предоставляет аналогичные внутренние и внешние форматы для TAI64NA.

libtai предоставляет struct caldate для хранения дат в форме год-месяц-день. Он может преобразовать struct caldate по григорианскому календарю в модифицированный номер дня в Юлиане для упрощения арифметики дат.

libtai предоставляет struct caltime для хранения календарных дат и времени вместе со смещениями UTC. Он может конвертировать из struct tai в struct caltime в UTC, учитывая високосные секунды, для точного отображения даты и времени. Он также может преобразовать обратно из struct caltime в struct tai для пользовательского ввода. Общая скорость преобразования UTC в TAI в 100 раз выше, чем в обычной реализации UNIX mktime ().

Эта версия libtai требует UNIX-системы с gettimeofday (). Будет легко портировать на другие операционные системы с компиляторами, поддерживающими 64-битную арифметику.

Исходный код libtai находится в открытом доступе.

Я думаю, что это просто библиотека для преобразования форматов времени. Я ищу программу, которая будет регулировать часы Linux. Ashley Yakeley 7 лет назад 0
В заголовке вашего вопроса написано «получить TAI», но не «использовать TAI для моих часов» или «установить систему в TAI». Когда вы упоминаете установку часов на TAI в теле, вам показалось, что вы применили эту опцию, если она позволит вам «получить правильный TAI из системы». dfc 7 лет назад 0
Я спрашиваю о часах Linux `CLOCK_TAI`. Ashley Yakeley 7 лет назад 0
3
Michael Firth

Поскольку я работаю chronyвместо старого ntpd, у меня не было автоматического способа получить правильный параметр ядра, поэтому я искал альтернативу.

Поскольку смещение между TAI и UTC является относительно постоянным (изменяется <раз в год), можно статически установить параметр ядра, а затем использование часов CLOCK_TAI в приложении даст правильное значение.

Существует тестовое приложение для установки смещения ядра в исходниках ядра, в tools/testing/selftests/timers/set-tai.c. И, если у вас установлен tzdataпакет, есть файл со смещением между UTC и TAI в /usr/share/zoneinfo/leap-seconds.list.

Я вырубил тестовое приложение ядра, поэтому основным стало:

int main(int argc, char **argv) { int i, ret;  ret = get_tai(); printf("tai offset started at %i\n", ret);  if (argc < 2) { printf("New offset not given, not setting\n"); } else { i = strtol(argv[1],NULL,10); printf("Attempting to set TAI offset to %d\n",i); printf("Checking tai offsets can be properly set: "); ret = set_tai(i); ret = get_tai(); if (ret != i) { printf("[FAILED] expected: %i got %i\n", i, ret); return EXIT_FAILURE; } } printf("[OK]\n"); return EXIT_SUCCESS; } 

Затем, для моего случая использования, это был просто вопрос извлечения правильного значения из leap-seconds.listфайла и запуска set-taiс этим параметром ( /etc/rc.localчтобы это произошло во время загрузки). Пример способа сделать это:

TAI_OFFSET=$(grep -v '^#' /usr/share/zoneinfo/leap-seconds.list | tail -1 | awk '{ print $2 }') if [ -x /usr/local/sbin/set-tai ]; then /usr/local/sbin/set-tai $TAI_OFFSET fi 

Надеюсь, что это полезно для кого-то еще!

Похожие вопросы