Die meisten Rechneruhren laufen sehr ungenau. Das gilt sowohl
für die Hardware-Uhr, /dev/rtc
, als auch für
die Software-Uhr im Unix kernel. Der Grund liegt in ungenauen
Quarzen, die für die Erzeugung der erforderlichen Taktfrequenzen
benutzt werden.
Soll die Uhrzeit auf dem Rechner genau sein, ist daher eine regelmäße Synchronisation mit einer externen Zeitreferenz notwendig.
Noch wichtiger als eine in genauer Übereinstimmung mit der gesetzlichen Zeit laufende Rechneruhr ist eine einheitliche Zeit bei mehreren Rechnern in einem lokalen Netz. Dies ist u.a. von Bedeutung wenn
Also sollten die Uhren im Netz untereinander oder sogar mit einer
genauen extern Referenz synchronisiert werden. Unter Unix wird dazu
allerdings nicht etwa der schon beschriebene system call
settimeofday
(2) benutzt. Die Zeit mit
settimeofday
(2) zu setzen hätte zwei Nachteile:
Beides hätte Nachteile für Programme, die
z.B. Zeitmessungen machen, oder in irgendeiner anderen Weise Zeiten
aus dem Unix kernel (gettimeofday
(2)) oder von Dateien
miteinander vergleichen.
Statt settimeofday
(2) wird der system call
adjtime
(2) bzw. moderner adjtimex
(2)
verwendet. Mit diesem system call kann man dem kernel einen
struct timeval
übergeben, der ihm mitteilt, um
wieviel Mikrosekunden seine Zeit vor- bzw. nachgeht.
Der tick value, der bei Linux/intel x86 normalerweise auf 10000
eingestellt ist, wird dann um 5 Mikrosekunden erhöht
bzw. erniedrigt, also auf 10005 bzw. 9995. Damit läuft die Uhr
dann um 0.05% schneller bzw. langsamer. Der kernel kann anhand des in
adjtime
(2) übergebenen Wertes einfach ausrechnen,
wie lange er die Uhr schneller bzw. langsamer laufen lassen muß,
bis diese Zeitdifferenz ausgeglichen ist. Geht die Uhr z.B. 10ms vor,
muß sie bei Linux/i386 für 2000 ticks (also etwa 20
Sekunden lang) langsamer laufen, denn 2000 ticks * 5 µs/tick =
10ms.
timed
Eine schon lange existierende Software zur Synchronisation von
Uhren auf Unix-Maschinen in einem LAN (Local Area Network), ist der
timed
. Dieser daemon wird typischerweise beim Booten im
Hintergrund gestartet und tauscht dann regelmäßig
Nachrichten mit time stamps mit den anderen time daemons im LAN aus.
Der timed
benutzt zum Austausch der Zeitinformation
kein eigenes Protokoll sondern bedient sich der ICMP Time Stamp
Request/Reply Nachrichten, die normalerweise in einem Unix kernel,
sowie auch in vielen anderen Systemen, schon vorhanden sind.
Jedes System im Internet muß ICMP implementiert haben und kennt normalerweise auch ICMP Time Stamps. Wenn eine Maschine im Internet eine ICMP Time Stamp Request erhält, antwortet sie normalerweise mit einem ICMP Time Stamp Reply an den Absender des Request. In der Antwort ist ein 32 Bit langer Wert enthalten, der die Zeit auf dem antwortenden System angibt. Dieser Time Stamp hat aber einige Nachteile:
Es gibt durchaus auch Geräte, wie z.B. Router, die mit Non-Standard Time Stamps antworten und z.B. die Anzahl der Millisekunden seit ihrem einschalten liefern. Sie sind damit natuerlich für Synchronisationszwecke nicht geeignet.
Der timed
besitzt noch einen weiteren Nachteil: Die
Time Stamps werden zwar mit ICMP ausgetauscht und können damit
beliebig viele Router passieren und jeden Rechner im Internet
erreichen, aber timed
benutzt UDP broadcast, um geeignete
als Server laufende timed
s im LAN zu finden, die dann
nach ICMP Time Stamps gefragt werden können. Da Broadcasts
typischerweise von Routern nicht weitergeleitet werden, ist die
Synchronisation mit timed
auch auf das LAN
beschränkt.
RFC 868
In RFC 868 ist ein weiteres Protokoll zur Zeitsynchronisation von Rechnern beschrieben. Das Protokoll kann sowohl über TCP als auch über UDP benutzt werden und verwendet in beiden Fällen den port 37.
Eine Anfrage eines clients auf dem entsprechenden port wird vom server mit einem 32 bit langen integer beantwortet, der die momentane Zeit darstellt. Die Zeit ist in dem integer kodiert als die Anzahl der Sekunden seit 1900-01-01 0:00:00 UTC, wobei der RFC nicht spezifiziert, ob Schaltsekunden mitgegzählt oder wie in POSIX ignoriert werden.
Auf Unix-Maschinen ist ein server nach RFC 868 normalerweise im
inetd
(8) implementiert, der einfach die aktuelle Zeit mit
time
(2) vom kernel besorgt und die Konstante 2208988800
addiert, also die Anzahl der Sekunden zwischen 1900-01-01 und
1970-01-01. Da der von time
(2) zurückgegebene
time_t
normalerweise POSIX-konform Schaltsekunden
ignoriert, werden auch von RFC-868-Servern Schaltsekunden meist nicht
mitgezählt.
Ein gravierender Nachteil von RFC 868 für die Synchronisation
von Rechnern ist die schlechte Genauigkeit der time stamps von nur 1s.
NTP
Alle Nachteile von timed
sind in einem neueren
Protokoll beseitigt worden. Das Network Time Protocol (NTP)
ist von David Mills an der University of Delaware entwickelt
worden und u.a. in RFC 1305 beschrieben.
NTP kennt nur ein Paket-Format, mit dem Zeitinformationen zwischen Rechnern ausgetauscht werden. Die NTP-Pakete enthalten im wesentlichen 4 time stamps von jeweils 64 bit:
Alle Zeiten werden in NTP als binäre 64 bit fixed point Zahlen mit 32 bits vor und 32 bits nach dem Komma dargestellt. Die Zeiten geben die Sekunden an, die seit einem bestimmten festgelegten Zeitpunkt vergangen sind. Dieser Zeitpunkt wurde so festgelegt, daß der Zeitpunkt 1972-01-01 0:00:00 UTC, also die Einführung von UTC, durch die Zahl 2272060800.0 dargestellt wird. Das bedeutet, daß der Zeitpunkt 0.0 der 1. Januar 1900 0:00:00 UTC ist, wenn man UTC entsprechend weit zurück definiert und keine Schaltsekunden vor 1972 annimmt.
Wegen der 32 binären Nachkommastellen ist die Auflösung der in NTP verwendeten Zeitdarstellung 2-32 s, also ca. 233 ps = 233 * 10-12s.
-- Beschreibung des Protokolls: server, client, stratum --
-- Schaltsekunden --
-- xntp und ntp4 --
-- Konfiguration --
-- public NTP server --
Auch die PTB betreibt zwei solche NTP server,
ntp1.ptb.de
und, ntp2.ptb.de
.
DCF-77, GPS, etc.
Wer sich die Zeit per NTP von einem anderen Rechner holen möchte, sollte relativ regelmäße Netzwerkverbindungen haben. Noch besser wäre eine ständig existierende Verbindung zum NTP server.
Die ist aber bei vielen Rechnern, die bei Privatanwendern zu Hause stehen, meist nicht gegeben. Es gibt es auch eine weitere Möglichkeit, an die genaue Zeit zu kommen.
Mit xntp kann man seinen Rechner nicht nur mit anderen Rechnern im
Netz mit NTP synchronisieren. Der xntp daemon, xntpd
,
kann auch mit einer ganzen Reihe von Zeitzeichenempfängern
zusammenarbeiten, die typischerweise an die serielle Schnittstelle
angeschlossen werden. Diese Empfänger erhalten die Zeit direkt
z.B. via Satellit im Falle von GPS (Global Positioning
System) oder von einem Langwellensender wie DCF-77, der
bei Frankfurt steht und von der PTB
betrieben wird, oder WWV, der vom
amerikanischen NIST in Boulder,
Colorado betrieben wird. Auch über Modems kann Zeitinformation
empfangen werden, z.B. wieder von der PTB unter der
Nummer 0531-512038, und entsprechende Treiber sind in xntp
vohanden. Auch NIST bietet Zeitinformationen über Modem an.
Da GPS-Empfänger recht teuer sind und die Zeitinformation per Modem Telefonkosten verursacht, bietet sich in Deutschland der Empfang der Zeit per DCF-77 an. Solche Empfänger zum Anschluß an die serielle Schnittstelle kann man sich leicht selbst aus Teilen für ca. 40 DM bauen. Schaltplan, Platinenlayout und Beschreibung der Schaltung gibt's auch hier. Man braucht dann nur noch eine freie serielle Schnittstelle. Evtl. muß man dazu noch eine Schnittstellenkarte besorgen, wenn an den beiden auf dem mainboard meistens vorhandenen seriellen Schnittstellen schon Maus und Modem hängen.
Der DCF-77-Sender sendet ein amplitudenmoduliertes Signal auf einem 77.5kHz-Träger. Die Amplitude wird beim Beginn jeder Sekunde auf 25% abgesenkt. Auf diesem Wert bleibt sie für 100 ms oder 200 ms und geht dann wieder auf 100%, und zwar für die nächsten 900 ms bzw. 800 ms bis zum Beginn der nächsten Sekunde.
Die Absenkung des Signals wird in der 59. Sekunde jeder Minute ausgelassen, um die Synchronisation mit dem Minutenbeginn zu ermöglichen. Wenn also eine fallende Flanke erst nach 1800 ms oder mehr nach der letzten Flanke empfangen wird, stellt sie einen Minutenbeginn dar.
Durch die fallenden Flanken zum Beginn der Sekunde bietet das Signal daher die Möglichkeit, sich mit dem Sekundentakt zu synchronisieren.
Außerdem wird jede Sekunde ein Bit an Information übertragen. Dauert die Absenkung der Amplitude 100 ms, wurde eine 0 übertragen, anderenfalls eine 1.
Pro Minute werden daher also 59 Bits an Information übertragen. Diese 59 Bits geben die Minute, Stunde, Tag, Monat, Jahr und Wochentag der nächsten Minute an. Außerdem sind in den 59 Bits auch Informationen über Winter-/Sommerzeit sowie Schaltsekunden enthalten.
Diese Informationen werden vom entsprechenden Treiber im
xntpd
genutzt, um die genaue Zeit zu ermittlen und die
Software-Uhr des Unix kernels mittels adjtime
(2) mit der
von DCF-77 gesendeten Zeit zu synchronisieren.
Wie gut diese Synchronisation ist, hängt vor allem davon ab, wie gut der verwendete DCF-77-Empfänger ist, d.h. wie genau die fallenden Flanken am Ausgang des Empfängers tatsächlich zum Sekundenbeginn auftreten.
...