ADJTIMEX(2)

ИМЯ
adjtimex - тонкая настройка часов в ядре

ОБЗОР
#define _BSD_SOURCE      /* Смотрите feature_test_macros(7) */
#include <sys/timex.h>
int adjtimex(struct timex *buf);

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

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

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

ADJ_OFFSET
    Установить смещение по времени из buf.offset.

ADJ_FREQUENCY
    Установить смещение частоты из buf.freq.

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.29)
    Добавить buf.time к текущему времени. Если в buf.status указан флаг ADJ_NANO, то значение buf.time.tv_usec считается заданным в наносекундах; в противном случае это микросекунды.

ADJ_MICRO (начиная с Linux 2.6.36)
    Выбрать микросекундной разрешение.

ADJ_NANO (начиная с Linux 2.6.36)
    Выбрать наносекундной разрешение. Должно быть указано что-то одно: ADJ_MICRO или ADJ_NANO.

ADJ_TAI (начиная с Linux 2.6.26)
    Установить смещение TAI (атомное международное время) из buf->константы. ADJ_TAI не должно использоваться вместе с ADJ_TIMECONST, так как последний режим также использует поле buf->константа. Подробное описание TAI и различия между TAI и UTC смотрите в BIPM (http://www.bipm.org/en/bipm/tai/tai.html)

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
    Вставить високосную секунду (чтение/запись).

STA_DEL
    Удалить високосную секунду (чтение/запись).

STA_UNSYNC
    Часы не синхронизированы (чтение/запись).

STA_FREQHOLD
    Зафиксировать частоту (чтение/запись).

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 (начиная с Linux 2.6.26)
    Источник часов (0 = A, 1 = B; только чтение).

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

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении adjtimex() возвращает состояние часов; то есть одно из следующих значений:

TIME_OK
    Часы синхронизированы.

TIME_INS
    Вставлена високосная секунда.

TIME_DEL
    Удалена високосная секунда.

TIME_OOP
    Происходит учёт високосной секунды.

TIME_WAIT
    Прошла високосная секунда.

TIME_ERROR
    Часы не синхронизированы. Символическое имя TIME_BAD — синоним TIME_ERROR, предоставляется для обратной совместимости.

При ошибке adjtimex() возвращается -1 и изменяется errno.

ОШИБКИ

EFAULT
    buf не является указателем на доступную для записи область памяти.

EINVAL
    Предпринята попытка установить buf.offset в значение, выходящее за диапазон от -131071 до +131071, или установить buf.status в значение отличное от перечисленных выше, или установить buf.tick в значение за пределами диапазона от 900000/HZ до 1100000/HZ, где HZ — частота прерываний системного таймера.

EPERM
    Значение buf.modes не равно 0 или ADJ_OFFSET_SS_READ и вызывающий не имеет необходимых прав. В Linux для этого требуется мандат CAP_SYS_TIME.

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

СООТВЕТСТВИЕ СТАНДАРТАМ
adjtimex() — это специфичный для Linux системный вызов и он не должен использоваться в программах, которые должны быть переносимыми. Существует похожий, более переносимый, более гибкий метод настройки системных часов adjtime(3).

СМОТРИТЕ ТАКЖЕ
settimeofday(2), adjtime(3), capabilities(7), time(7), adjtimex(8)