Основные способы для Linux
В действительности, в Linux имеются две параллельные системы учета времени:
одна - это часы с питанием от батарей - "Часы Реального Времени" (так же
известные как "ЧРВ", "RTC", "CMOS clock", "аппаратные часы"), которые идут
тогда, когда компьютер выключен, но не используются, когда система
функционирует. Другая - "системные часы" (иногда называемые "часы ядра" или
"программные часы") является программным счетчиком, основанном на системном
прерывании. Системные часы не идут, когда система выключена, поэтому они
устанавливаются от ЧРВ (или какого-либо другого источника) во время
загрузки. Ссылки на часы в документации ntpd относятся к системным часам, а
не ЧРВ.
Обе системы будут идти с разной скоростью, отрываться друг от друга и от
реального времени. Самый простой способ корректировать их - это измерить
величину их отклонения и внести его в программу, контролирующую их. ЧРВ
используется только, когда система выключена, они корректируются во время
загрузки, при помощи clock(8) или hwclock(8). Системные часы корректируются при помощи
ранее заданной величины, которую система учитывает при каждой команде
прерывания, пришедшей от часов, используя программу adjtimex(8).
Альтернативой adjtimex(8) может служить
chron, которая после запуска clock(8) или hwclock(8)
периодически синхронизирует системное время с (корректированными) ЧРВ. Эта
схема работы рекомендуется в документации к clock(8), ее можно использовать, если вы
запускаете ее часто и не делаете больших "прыжков" в системных часах, но
but adjtimex(8) - это более красивое решение. Некоторые программы могут
привести к ошибке, если будет совершен "прыжок" назад.
Следующий шаг - это использование программ типа ntpd, которые регулярно
сверяют часы в сети или с радио, и постоянно корректируют системное время.
Если у вас есть постоянное подключение к сети во время загрузки, вы можете
не использовать ЧРВ, а вместо этого, использовать программу ntpdate (которая
входит в состав ntpd) для установки системных часов при помощи часового
сервера в Интернете или локальной сети. Но, если у вас иногда не будет
сетевого соединения, или вам понадобится точное время во время загрузки до
того, как соединение будет активировано, то вам придется использовать ЧРВ.
Но, в этом случае, вам , наверное, хотелось бы синхронизировать ЧРВ с
откорректированными системными часами. Но это будет иметь практическое
значение, если система выключена лишь несколько минут.
Но если система все время находится в рабочем состоянии, и перезагружается
сразу после того, как выключится, тогда вы можете корректировать ЧРВ,
основываясь на показаниях системных часов перед самой перезагрузкой. ЧРВ во
время перезагрузки не отклонятся на значительную величину, и поэтому у вас
не возникнет необходимости выяснять эту погрешность.
Конечно система может перезагрузиться во внештатном режиме, поэтому
некоторые ядра синхронизируют ЧРВ с системными часами каждые 11 минут, в
случае, если системные часы корректируются другой программой. Погрешность
на ЧРВ не будет большой за 11 минут, но если система была отключена на
большее время, то возникает проблема - программам, которые
корректируют ЧРВ, понадобится узнать точное время последнего выключения
системы, а ядро не сохраняет такую информацию.
Некоторые "закоренелые" пользователи Unix могут пожать плечами, если
услышат, что Linux установлен на машину, которая не работает круглосуточно,
но некоторые из нас работают на двойных платформах или используют Linux на
портативных компьютерах, которые выключают после работы. Другие просто не
любят оставлять машину включенной на долгое время, если на ней не работают.
Таким образом, достоинство проверки "каждые 11 минут" превращается в
недостаток.
Это "достоинство/недостаток" ведет себя по-разному в разных версиях ядра
(возможно, и в различных версиях xntpd и
ntpd), поэтому, если вы используете ntpd
совместно с hwclock, то вам, очевидно, потребуется проверить свою систему
для того, чтобы узнать в точности, что происходит. Если у вас нет
возможности предотвратить коррекцию ЧРВ ядром, то вам лучше работать с
нулевой величиной коррекции.
Исходный текст части ядра, который управляет этим процессом, находится в
файле /usr/src/linux-номер_версии/arch/i386/kernel/time.c (где
номер_версии - это версия вашего ядра). Если переменная time_status
установлена на TIME_OK , то ядро будет копировать системное время в ЧРВ
каждые 11 минут, иначе ядро не корректирует ЧРВ. Эту процедуру можно также
выполнить при помощи adjtimex(2) (это делается, например, в ntpd и timed).
Обращение к settimeofday(2) установит time_status в TIME_UNSYNC; в
результате этого, ядро не будет корректировать ЧРВ. Я не нашел документации
по этому вопросу.
Если вам требуется точность в доли секунды, вам потребуется лишь hwclock(8)
и adjtimex(8). В принципе, можно легко установить часы по сети, но я
использую старую программу clock(8) и она меня еще ни разу не подводила. С
другой стороны, если у вас есть несколько машин в локальной сети, то было
бы сподручнее синхронизировать их друг с другом.