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(), те же самые, но названные по-другому). Является битовой маской, содержащей побитовую (или) комбинацию нуля или более следующих бит:

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

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

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

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

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

Включить обновление фазовой подстройки частоты (PLL) через ADJ_OFFSET.
Включить частотную дисциплину обслуживания PPS (импульсов в секунду).
Включить временную дисциплину обслуживания PPS.
Выбрать режим частотной подстройки частоты (FLL).
Вставить високосную секунду за последней секундой дня UTC, то есть удлинить последнюю минуту дня на одну секунду. Вставка високосной секунды будет происходить каждый день пока установлен этот флаг.
Удалить високосную секунду из последней секунды дня UTC. Удаление високосной секунды будет происходить каждый день пока установлен этот флаг.
Часы не синхронизированы.
Зафиксировать частоту. Обычно корректировки, внесённые через результат ADJ_OFFSET, приводят к ослаблению также проводимых настроек по частоте. Таким образом, единичный вызов исправляет текущее смещение, но поскольку смещения в том же направлении делаются неоднократно, маленькие изменения по частоте будут накапливаться, чтобы исправить длинный сдвиг.
Данный флаг отключает маленькие исправления по частоте при корректировке значения ADJ_OFFSET.
Присутствует сигнал PPS (импульсов в секунду).
Превышено искажение сигнала PPS.
Превышено отклонение сигнала PPS.
Ошибка калибровки сигнала PPS.
Проблема с аппаратурой часов.
Единица данных (0 = микросекунды, 1 = наносекунды). Устанавливается с помощью ADJ_NANO, очищается с помощью ADJ_MICRO.
Режим (0 = фазовая подстройка частоты, 1 = частотная подстройка частоты).
Источник часов (0 = A, 1 = B); не используется.

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

Библиотечная функция 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() возвращают состояние часов, а именно одно из следующих значений:

Часы синхронизированы, подстройки високосной секундой не ожидается.
Показывает, что в конце дня по UTC будет добавлена високосная секунда.
Показывает, что в конце дня по UTC будет удалена високосная секунда.
Выполняется вставка високосной секунды.
Выполнена вставка или удаление високосной секунды. Это значение возвращается при следующей операции ADJ_STATUS по очистке флагов STA_INS и STA_DEL.
Системное время не синхронизировано с авторитетным сервером. Это значение возвращается при любом утвердительном значении следующего:
  • Установлен 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.

ОШИБКИ

buf не является указателем на доступную для записи область памяти.
Попытка установить buf.freq в значение вне диапазона (-33554432, +33554432).
Попытка установить buf.offset в значение вне разрешённого диапазона. В ядрах до Linux 2.0 допустимым диапазоном был (-131072, +131072). Начиная с Linux 2.0 и новее допустимым диапазоном является (-512000, +512000).
Попытка установить buf.status в значение, отличное от перечисленных выше.
Предпринята попытка установить buf.tick в значение вне диапазона от 900000/HZ до 1100000/HZ, где HZ — частота прерываний системного таймера.
Значение 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