ОБЗОР
#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
- 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.