|
Bog BOS: Работа со временем |
Последние изменения: |
Последнее изменение файла: 2018.08.10
Скопировано с www.bog.pp.ru: 2024.11.21
Используются различные системы отсчета времени, основанные на астрономических наблюдениях, периоде атомных колебаний и смешанные:
Есть модификации UTC:
DUT1 - разница между UTC и UT1 точностью до 0.1 секунды, публикуется еженедельно обсерваторией США.
Юлианский день - номер дня с полудня 1 января 4713 года до н.э. Модифицированный Юлианский день есть Юлианский день - 2400000.5 (т.е. 0 - это начало нашей эры). При этом необходимо указывать систему времени (TAI, UT).
В компьютере имеется 2 реализации часов: часы реального времени (Real Time Clock - RTC, CMOS clock, hardware clock, /dev/rtc, /proc/driver/rtc) и системные часы (system clock, software clock). Часы реального времени представляют собой отдельную микросхему, питающуюся от литиевой батарейки (от нее питается также CMOS, хранящий настройки BIOS), и работают независимо от того, включен компьютер или нет. ОС при загрузке (/etc/rc.sysinit) считывает текущее время, после чего ведет свой счетчик времени (системные часы) самостоятельно основываясь на подсчете количества специальных регулярных прерываний (timer interrupt), обычно 100 Гц (1024 Гц). Системное время выражается в числе секунд (и микросекунд или наносекунд) после 00:00:00 January 1, 1970 UTC.
Показания этих часов могут отличаться друг от друга (и от реального времени ;). Чтение и запись RTC, согласование RTC и системного времени осуществляются программой hwclock(8) (в старых версиях Linux clock(8)). hwclock позволяет использовать RTC в режиме UTC или местного времени (см. переменные окружения в /etc/sysconfig/clock). Информация о расхождении хранится в файле /etc/adjtime.
Значение системных часов можно изменять командой date(1), но лучше этого не делать, т.к. многие программы не выносят разрывов и тем более уменьшения показания системных часов (например, старая версия X Window просто зависала при этом; на новой я не проверял ;). NTP (см. ниже) использует плавную подстройку частоты часов для коррекции текущего времени (по умолчанию, в небольших пределах, но их можно расширить). Позднее утилита adjtimex(8) (adjtime в SVR4) была выделена в отдельный пакет (adjtimex-1.11-5 для RH 7.2), что позволяет плавно подстраивать значение системных часов и корректировать их частоту с помощью сигналов точного времени (требуется несколько дней, --log --watch) или сделав пару запросов в день к NTP серверу с помощью ключа --host (полезно при модемном подключении к интернет). Позволяет также согласовать ход аппаратных и системных часов (предлагаемые корректировки можно получить командой: adjtimex --compare, только надо немного подождать). Не стоит использовать одновременно NTP и adjtimex или hwclock --adjust или hwclock --hctosys. Исчезла в RHEL 3 (White Box 3.0, CentOS 3).
Стабильность частоты типичного кварцевого генератора невелика (например, зависит от температуры, напряжения, механических деформаций и т.д.), к тому же базовая частота меняется от кристалла к кристаллу (считается допустимым отклонение частоты в 500 PPM, что приводит к уходу системных часов на 40 секунд в день; PPM - одна миллионная). Согласование хода аппаратных и системных часов с помощью adjtimex увеличивает точность хода, но недостаточно для работы сервера.
Системные часы серверов должны быть согласованы (синхронизированы) между собой с большой точностью (при небольшой загрузке - доли секунды) иначе невозможно отслеживать последовательность событий, разбирать журналы сообщений и т.д. Чем больше плотность событий (загрузка сервера), тем более точной должна быть синхронизация. При синхронизации обычно используется система времени UTC. В Интернет (TCP/IP) возможны следующие методы синхронизации:
Для более точной (субмикросекунда) синхронизации в локальной сети может использоваться протокол PTP (Precision Time Protocol v2, IEEE 1588), использующий аппаратные отметки точного времени, которые ставятся на входящих и исходящих PTP пакетах сетевыми контроллерами и коммутаторами, имеющими собственные часы. Для достижения субмикросекундной точности требуется поддержка ото всех элементов локальной сети, в противном случае рекомендуется оставаться на NTP. Не надо синхронизовать системные часы одновременно по NTP и по PTP, для этого есть утилита timemaster. Проверка наличия поддержки PTP в драйвере сетевого контроллера: "ethtool -T имя-интерфейса". Протокол PTP используют серверы chrony и ptp4l (linuxptp), Элементы локальной сети автоматически (алгоритм BMC) выстраиваются в иерархию (master-slave), в вершине которой находятся суперчасы (grandmaster), листья (и вершина) дерева имеют 1 порт и называются обычными (ordinary) часами, узлы с несколькими портами называются граничными (boundary) часами. Аппаратные часы (PHC) хоста (сетевого контроллера) синхронизируются аппаратно со старшими часами, системные часы синхронизируются программно со старшими часами. PTP использует систему отсчёта времени TAI в отличие от системного времени, используещег UTC. В настоящий момент разница между ними - 36 секунд.
http://tycho.usno.navy.mil/tzones.html
/usr/share/zoneinfo, tzfile(5), zic(8), TZ, /etc/localtime, /etc/sysconfig/clock
Задание в Cisco IOS часового пояса и даты перехода на дневное время.
Время в UNIX отсчитывается в секундах (микросекундах) с 1 января 1970 года.
Преобразование из внутреннего формата в человеческий:
Преобразование из человеческого времени во внутреннее:
Преобразование времени изменения файла в "лексикографический" вид (20010905122716):
{ if ( $2 == "Jan" ) m = "01"; else if ( $2 == "Feb" ) m = "02"; else if ( $2 == "Mar" ) m = "03"; else if ( $2 == "Apr" ) m = "04"; else if ( $2 == "May" ) m = "05"; else if ( $2 == "Jun" ) m = "06"; else if ( $2 == "Jul" ) m = "07"; else if ( $2 == "Aug" ) m = "08"; else if ( $2 == "Sep" ) m = "09"; else if ( $2 == "Oct" ) m = "10"; else if ( $2 == "Nov" ) m = "11"; else if ( $2 == "Dec" ) m = "12"; if ( $3 < 10 ) dat = $1 m "0" $3 substr($4,1,2) substr($4,4,2) substr($4,7,2); else dat = $1 m $3 substr($4,1,2) substr($4,4,2) substr($4,7,2); print dat; }
Преобразование времени изменения файла во внутренний формат:
#!/usr/bin/perl use Time::Local; eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if $running_under_some_shell; eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift; # process any FOO=bar switches $[ = 1; # set array base to 1 $, = ' '; # set output field separator $\ = "\n"; # set output record separator while (<>) { ($year,$month,$day,$time) = split(' ', $_, 9999); if ($month eq 'Jan') { $M = 1; } elsif ($month eq 'Feb') { $M = 2; } elsif ($month eq 'Mar') { $M = 3; } elsif ($month eq 'Apr') { $M = 4; } elsif ($month eq 'May') { $M = 5; } elsif ($month eq 'Jun') { $M = 6; } elsif ($month eq 'Jul') { $M = 7; } elsif ($month eq 'Aug') { $M = 8; } elsif ($month eq 'Sep') { $M = 9; } elsif ($month eq 'Oct') { $M = 10; } elsif ($month eq 'Nov') { $M = 11; } elsif ($month eq 'Dec') { $M = 12; } print timelocal( substr($time,7,2), substr($time,4,2), substr($time,1,2), $day, $M-1, $year ); }
|
Bog BOS: Работа со временем |
Последние изменения: |