ИМЯ
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
"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,
выполняется
ядром в
контексте
таймера.
Следовательно,
для
установки
или
удаления
високосной
секунды
потребуется
один тик
для
перехода.