adjtimex(2)

ADJTIMEX(2) Руководство программиста Linux ADJTIMEX(2)

ИМЯ

adjtimex, ntp_adjtime - тонкая настройка часов в ядре

ОБЗОР

#include <sys/timex.h>
int adjtimex(struct timex *buf);
int ntp_adjtime(struct timex *buf);

ОПИСАНИЕ

В Linux для подстройки часов используется алгоритм Дэвида Л. Миллса (David L. Mills) (смотрите RFC 5905). Системный вызов adjtimex() читает и (необязательно) устанавливает параметры подстройки для этого алгоритма. Он берёт указатель на структуру timex, изменяет параметры ядра согласно значениям (некоторых) её полей и возвращает эту уже обновлённую структуру с текущими значениями параметров ядра. Данная структура объявлена так:


struct timex {

int modes; /* выбор режима */
long offset; /* смещение по времени; в наносекундах, если
установлен флаг состояния STA_NANO, иначе
в микросекундах */
long freq; /* смещение частоты; единицы измерения */
описаны в ЗАМЕЧАНИЯХ */ long maxerror; /* максимальная ошибка (микросекунды) */
long esterror; /* ожидаемая ошибка (микросекунды) */
int status; /* команда/состояние для часов */
long constant; /* константа времени PLL (phase-locked loop) */
long precision; /* точность часов
(микросекунды, только чтение) */
long tolerance; /* допуск тактовой частоты (только чтение);
единицы измерения описаны в ЗАМЕЧАНИЯХ */
struct timeval time;
/* текущее время (только чтение, кроме
ADJ_SETOFFSET); при возврате в time.tv_usec
содержатся наносекунды, если установлен флаг
STA_NANO, иначе микросекунды */
long tick; /* микросекунд между тиками часов */
long ppsfreq; /* частота PPS (импульсов в секунду)
(только чтение); единицы измерения описаны в
ЗАМЕЧАНИЯХ */
long jitter; /* искажение PPS (только чтение); в наносекундах,
если установлен флаг состояния STA_NANO,
иначе в микросекундах
int shift; /* длительность интервала PPS
(секунды, только чтение) */
long stabil; /* устойчивость PPS (только чтение);
единицы измерения описаны в ЗАМЕЧАНИЯХ */
long jitcnt; /* счётчик превышений ограничения искажения
PPS (только чтение) */
long calcnt; /* счётчик интервалов калибровки PPS
(только чтение) */
long errcnt; /* счётчик ошибок калибровки PPS
(только чтение) */
long stbcnt; /* счётчик событий превышения ограничения
устойчивости PPS (только чтение) */
int tai; /* смещение TAI offset, установленное предыдущей
операцией ADJ_TAI (секунды, только чтение,
начиная с Linux 2.6.26) */
/* далее идут байты заполнения, для расширения структуры в будущем */ };

Полем modes определяется какие параметры, если это необходимо, устанавливаются (как описывалось выше, константы, используемые в ntp_adjtime(), те же самые, но названные по-другому). Является битовой маской, содержащей побитовую (или) комбинацию нуля или более следующих бит:

ADJ_OFFSET
Установить смещение по времени из buf.offset. Начиная с Linux 2.6.26, переданное значение ограничивается диапазоном (-0.5s, +0.5s). В старых ядрах, если значение выходит из диапазона, то возвращается ошибка EINVAL.
ADJ_FREQUENCY
Установить смещение по частоте из buf.offset. Начиная с Linux 2.6.26, переданное значение ограничивается диапазоном (-32768000, +32768000) В старых ядрах, если значение выходит из диапазона, то возвращается ошибка EINVAL.
ADJ_MAXERROR
Установить максимальную ошибку времени из buf.maxerror.
ADJ_ESTERROR
Установить ожидаемую ошибку времени из buf.esterror.
ADJ_STATUS
Установить биты состояния часов из buf.status. Описание бит представлено ниже.
ADJ_TIMECONST
Установить константу времени PLL из buf.constant. Если не задан флаг состояния STA_NANO (смотрите ниже), то ядро добавляет к этому значению 4.
ADJ_SETOFFSET (начиная с Linux 2.6.39)
Добавить buf.time к текущему времени. Если в buf.status указан флаг ADJ_NANO, то значение buf.time.tv_usec считается заданным в наносекундах; в противном случае это микросекунды.
ADJ_MICRO (начиная с Linux 2.6.26)
Выбрать микросекундной разрешение.
ADJ_NANO (начиная с Linux 2.6.26)
Выбрать наносекундной разрешение. Должно быть указано что-то одно: ADJ_MICRO или ADJ_NANO.
ADJ_TAI (начиная с Linux 2.6.26)
Установить смещение TAI (атомное международное время) из buf.constant.
ADJ_TAI не должно использоваться вместе с ADJ_TIMECONST, так как последний режим также использует поле buf.constant.
Подробное описание TAI и различия между TAI и UTC смотрите в BIPM
ADJ_TICK
Установить значение тика из buf.tick.

Также в modes можно указывать любое из следующих значений (многобитовая маска), биты которых нельзя указать в modes:

ADJ_OFFSET_SINGLESHOT
Старый вариант adjtime(): (постепенно) корректировать время значением, указанным в buf.offset, которое задаётся в микросекундах.
ADJ_OFFSET_SS_READ (работает, начиная с Linux 2.6.28)
Получить (в buf.offset) остаток необходимого откорректированного времени после выполнения операции ADJ_OFFSET_SINGLESHOT. Это возможность была добавлена в Linux 2.6.24, но работала неправильно до Linux 2.6.28.

Обычные пользователи могут задавать в modes значение ноль или ADJ_OFFSET_SS_READ. Только суперпользователь может задавать любые параметры.

Поле buf.status представляет собой битовую маску, используется для установки/получения битов состояния, связанных с реализацией NTP. Одни биты в маске можно и читать, и изменять, другие — только читать.

STA_PLL (чтение-запись)
Включить обновление фазовой подстройки частоты (PLL) через ADJ_OFFSET.
STA_PPSFREQ (чтение-запись)
Включить частотную дисциплину обслуживания PPS (импульсов в секунду).
STA_PPSTIME (чтение-запись)
Включить временную дисциплину обслуживания PPS.
STA_FLL (чтение-запись)
Выбрать режим частотной подстройки частоты (FLL).
STA_INS (чтение-запись)
Вставить високосную секунду за последней секундой дня UTC, то есть удлинить последнюю минуту дня на одну секунду. Вставка високосной секунды будет происходить каждый день пока установлен этот флаг.
STA_DEL (чтение-запись)
Удалить високосную секунду из последней секунды дня UTC. Удаление високосной секунды будет происходить каждый день пока установлен этот флаг.
STA_UNSYNC (чтение-запись)
Часы не синхронизированы.
STA_FREQHOLD (чтение-запись)
Зафиксировать частоту. Обычно корректировки, внесённые через результат ADJ_OFFSET, приводят к ослаблению также проводимых настроек по частоте. Таким образом, единичный вызов исправляет текущее смещение, но поскольку смещения в том же направлении делаются неоднократно, маленькие изменения по частоте будут накапливаться, чтобы исправить длинный сдвиг.
Данный флаг отключает маленькие исправления по частоте при корректировке значения ADJ_OFFSET.
STA_PPSSIGNAL (только чтение)
Присутствует сигнал PPS (импульсов в секунду).
STA_PPSJITTER (только чтение)
Превышено искажение сигнала PPS.
STA_PPSWANDER (только чтение)
Превышено отклонение сигнала PPS.
STA_PPSERROR (только чтение)
Ошибка калибровки сигнала PPS.
STA_CLOCKERR (только чтение)
Проблема с аппаратурой часов.
STA_NANO (только чтение; начиная с Linux 2.6.26)
Единица данных (0 = микросекунды, 1 = наносекунды). Устанавливается с помощью ADJ_NANO, очищается с помощью ADJ_MICRO.
STA_MODE (начиная с Linux 2.6.26)
Режим (0 = фазовая подстройка частоты, 1 = частотная подстройка частоты).
STA_CLK (только чтение; начиная c Linux 2.6.26)
Источник часов (0 = A, 1 = B); не используется.

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

ntp_adjtime ()

Библиотечная функция ntp_adjtime() (описана в NTP "Kernel Application Program API", KAPI) является более переносимым интерфейсом для выполнения той же задачи, что и adjtimex(). Она идентична adjtime() кроме следующего:

  • Константы, используемые в modes, начинаются с «MOD_», а не с «ADJ_», и содержат одинаковые суффиксы (MOD_OFFSET, MOD_FREQUENCY, and so on), кроме:
  • MOD_CLKA — синоним ADJ_OFFSET_SINGLESHOT.
  • MOD_CLKB — синоним ADJ_TICK.
  • Синонима для ADJ_OFFSET_SS_READ в KAPI нет.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении adjtimex() и ntp_adjtime() возвращают состояние часов, а именно одно из следующих значений:

TIME_OK
Часы синхронизированы, подстройки високосной секундой не ожидается.
TIME_INS
Показывает, что в конце дня по UTC будет добавлена високосная секунда.
TIME_DEL
Показывает, что в конце дня по UTC будет удалена високосная секунда.
TIME_OOP
Выполняется вставка високосной секунды.
TIME_WAIT
Выполнена вставка или удаление високосной секунды. Это значение возвращается при следующей операции ADJ_STATUS по очистке флагов STA_INS и STA_DEL.
TIME_ERROR
Системное время не синхронизировано с авторитетным сервером. Это значение возвращается при любом утвердительном значении следующего:
  • Установлен STA_UNSYNC или STA_CLOCKERR.
  • Флаг STA_PPSSIGNAL сброшен и установлен STA_PPSFREQ или STA_PPSTIME.
  • Установлены флаги STA_PPSTIME и STA_PPSJITTER.
  • Установлен флаг STA_PPSFREQ и STA_PPSWANDER или STA_PPSJITTER.
Символическое имя TIME_BAD — синоним TIME_ERROR, предоставляется для обратной совместимости.

Заметим, что начиная с Linux 3.4 вызов выполняется асинхронно и возвращаемое значение, обычно, не отражает состояние, изменённое самим вызовом.

При ошибке эти вызовы возвращают -1 и изменяют errno.

ОШИБКИ

EFAULT
buf не является указателем на доступную для записи область памяти.
EINVAL (до Linux 2.6.26)
Попытка установить buf.freq в значение вне диапазона (-33554432, +33554432).
EINVAL (до Linux 2.6.26)
Попытка установить buf.offset в значение вне разрешённого диапазона. В ядрах до Linux 2.0 допустимым диапазоном был (-131072, +131072). Начиная с Linux 2.0 и новее допустимым диапазоном является (-512000, +512000).
EINVAL
Попытка установить buf.status в значение, отличное от перечисленных выше.
EINVAL
Предпринята попытка установить buf.tick в значение вне диапазона от 900000/HZ до 1100000/HZ, где HZ — частота прерываний системного таймера.
EPERM
Значение buf.modes не равно 0 или ADJ_OFFSET_SS_READ и вызывающий не имеет необходимых прав. В Linux для этого требуется мандат CAP_SYS_TIME.

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes(7).

Интерфейс Атрибут Значение
ntp_adjtime() Безвредность в нитях MT-Safe

СООТВЕТСТВИЕ СТАНДАРТАМ

Эти интерфейсы не описаны в POSIX.1

Вызов adjtimex() есть только в Linux и не должен использоваться в переносимых программах.

Предпочтительным программным интерфейсом для службы NTP является ntp_adjtime().

ЗАМЕЧАНИЯ

В структуре timex, freq, ppsfreq и stabil ppm (частей на миллион) имеет 16-битную дробную часть, что означает, что значение 1 в одном из этих полей в действительности равно 2^-16 ppm, и 2^16=65536 равно 1 ppm. Это действительно как для входных (в случае freq) так и для выходных значений.

Обработка високосной секунды, возникающая при установке STA_INS и STA_DEL, выполняется ядром в контексте таймера. Следовательно, для установки или удаления високосной секунды потребуется один тик для перехода.

СМОТРИТЕ ТАКЖЕ

settimeofday(2), adjtime(3), ntp_gettime(3), capabilities(7), time(7), adjtimex(8), hwclock(8)

NTP "Kernel Application Program Interface"

2019-03-06 Linux