Die UNIX-Zeit wird auf Ihrem Computer unter UNIX gemessen.
Diese Antwort wird von Ihnen erwarten, dass Sie wissen, was die koordinierte Weltzeit (UTC), die internationale Atomzeit (TAI) und die SI-Sekunde sind. Ihre Erklärung geht weit über den Rahmen von Unix und Linux Stack Exchange hinaus. Dies ist nicht der Physik- oder Astronomiestapel-Austausch.
Die Hardware
Ihr Computer enthält verschiedene Oszillatoren, die Uhren und Timer steuern. Genau das, was es hat, variiert von Computer zu Computer, abhängig von seiner Architektur. Aber in der Regel und in sehr allgemeinen Worten:
- Es gibt irgendwo einen programmierbaren Intervall-Timer (PIT), der so programmiert werden kann, dass er eine bestimmte Anzahl von Oszillationen zählt und einen Interrupt an die Zentraleinheit auslöst.
- Da ist ein dem Zentralprozessor Zykluszähler, der für jeden ausgeführten Befehlszyklus einfach 1 zählt.
Die Theorie der Funktionsweise, in sehr weit gefassten Worten
Der Betriebssystemkern verwendet die PIT, um Ticks zu generieren . Es setzt die PIT auf Freilauf, zählt die richtige Anzahl von Oszillationen für ein Zeitintervall von beispielsweise einer Hundertstelsekunde, erzeugt einen Interrupt und setzt dann die Zählung automatisch zurück, um sie erneut durchzuführen. Es gibt Variationen darüber, aber im Wesentlichen verursacht dies a Tick- Interrupt mit einer festen Frequenz ausgelöst wird.
In der Software erhöht der Kernel jeden Tick einen Zähler. Es kennt die Tick-Frequenz, weil es die PIT an erster Stelle programmiert hat. Es weiß also, wie viele Zecken eine Sekunde ausmachen. Hiermit kann ermittelt werden, wann ein Zähler erhöht werden muss, der Sekunden zählt. Letzteres ist die Kernel-Idee von "UNIX Time". Es zählt in der Tat einfach mit einer Geschwindigkeit von einer Sekunde pro Sekunde nach oben, wenn es seinen eigenen Geräten überlassen wird.
Vier Dinge erschweren dies, die ich sehr allgemein darstellen werde.
Hardware ist nicht perfekt. Ein PIT, dessen Datenblatt besagt, dass es eine Oszillatorfrequenz von N Hertz hat, könnte stattdessen eine Frequenz von (sagen wir) N, 00002 Hertz haben, mit den offensichtlichen Konsequenzen.
Dieses Schema arbeitet sehr schlecht mit der Energieverwaltung zusammen, da die CPU hunderte Male pro Sekunde aufwacht, um nur eine Zahl in einer Variablen zu erhöhen. So haben einige Betriebssysteme sogenannte "tickless" -Designs. Anstatt die PIT zu veranlassen, für jeden Tick einen Interrupt zu senden, berechnet der Kernel (aus dem Low-Level-Scheduler), wie viele Ticks ohne auslaufende Thread-Quanten vergehen, und programmiert die PIT so, dass sie für diese vielen Ticks in den Scheduler zählt Zukunft vor der Ausgabe eines Tick-Interrupts. Es weiß, dass es dann den Durchgang von N Ticks beim nächsten Tick-Interrupt anstelle von 1 Tick aufzeichnen muss .
Anwendungssoftware kann die aktuelle Uhrzeit des Kernels ändern. Es kann Schritt den Wert oder es kann erschlug den Wert. Beim Schwenken wird die Anzahl der Ticks angepasst, die zum Erhöhen des Sekundenzählers benötigt werden. Der Sekundenzähler zählt also ohnehin nicht unbedingt mit einer Rate von eins pro SI-Sekunde , selbst wenn perfekte Oszillatoren vorausgesetzt werden. Schritt für Schritt wird einfach eine neue Zahl in den Sekundenzähler geschrieben, was normalerweise erst 1 SI Sekunde nach dem Ankreuzen der letzten Sekunde geschieht.
Moderne Kernel zählen nicht nur Sekunden, sondern auch Nanosekunden. Aber es ist lächerlich und oft völlig undurchführbar, wenn ein Tick-Interrupt einmal pro Nanosekunde erfolgt. Hier kommen Dinge wie der Zykluszähler ins Spiel. Der Kernel merkt sich bei jeder Sekunde (oder bei jedem Tick) den Wert des Zykluszählers und kann aus dem aktuellen Wert des Zählers ableiten, wann etwas die Zeit in Nanosekunden wissen möchte, wie viele Nanosekunden seit der letzten Sekunde vergangen sein müssen (oder Tick). Auch hier ist das Strom- und Wärmemanagement von großer Bedeutung, da sich die Häufigkeit des Befehlszyklus ändern kann. Kernels sind daher beispielsweise auf zusätzliche Hardware wie beispielsweise einen High Precision Event Timer (HPET) angewiesen.
Die C-Sprache und POSIX
Die Standard - Bibliothek der C - Sprache beschreibt Zeit in Bezug auf eine undurchsichtige Art, time_t
eine Strukturtyp tm
mit verschiedenen festgelegten Bereichen und verschiedene Bibliotheksfunktionen wie time()
, mktime()
und localtime()
.
Kurz gesagt: Die C-Sprache selbst garantiert lediglich, dass time_t
es sich um einen der verfügbaren numerischen Datentypen handelt und dass die difftime()
Funktion die einzig zuverlässige Methode zur Berechnung von Zeitdifferenzen ist . Es ist der POSIX-Standard, der strengere Garantien bietet, die time_t
tatsächlich zu den ganzzahligen Typen gehören und die Sekunden seit der Epoche zählen . Es ist auch der POSIX-Standard, der den timespec
Strukturtyp spezifiziert .
Die time()
Funktion wird manchmal als Systemaufruf bezeichnet. Tatsächlich war es heutzutage für viele Systeme lange nicht mehr der zugrunde liegende Systemaufruf. Unter FreeBSD ist beispielsweise der zugrunde liegende Systemaufruf clock_gettime()
, für den verschiedene "Uhren" verfügbar sind, die auf verschiedene Weise in Sekunden oder Sekunden + Nanosekunden messen. Mit diesem Systemaufruf liest die Anwendungssoftware die UNIX-Zeit aus dem Kernel. (Ein passender clock_settime()
Systemaufruf ermöglicht es ihnen, darauf zuzugreifen, und ein adjtime()
Systemaufruf ermöglicht es ihnen, darauf zuzugreifen.)
Viele Leute schwenken den POSIX-Standard mit sehr eindeutigen und genauen Aussagen darüber, was er vorschreibt. Solche Leute haben den POSIX-Standard meistens nicht gelesen . Die Idee, "Sekunden seit der Epoche" zu zählen, was der Standard verwendet, legt absichtlich nicht fest, dass POSIX-Sekunden die gleiche Länge wie SI-Sekunden haben und dass das Ergebnis von gmtime()
"notwendig" ist UTC trotz seines Aussehens ". Der POSIX-Standard ist absichtlichlocker genug, um beispielsweise ein UNIX-System zu ermöglichen, auf dem der Administrator die Schaltsekundeneinstellungen manuell korrigiert, indem er die Uhr in der Woche danach neu einstellt. In der Tat weist das Grundprinzip darauf hin, dass es absichtlich locker genug ist, um Systeme aufzunehmen, bei denen die Uhr absichtlich auf eine andere Zeit als die aktuelle UTC-Zeit eingestellt wurde.
UTC und TAI
Die vom Kernel erhaltene Interpretation der UNIX-Zeit hängt von den Bibliotheksroutinen ab, die in Anwendungen ausgeführt werden. POSIX gibt eine Identität zwischen der Kernelzeit und einer "Ausfallzeit" in a an struct tm
. Aber, wie Daniel J. Bernstein einmal betonte, war diese Identität in der Ausgabe von 1997 peinlich falsch, was die Schaltjahrregel des Gregorianischen Kalenders (etwas, das Schulkinder lernen) durcheinander brachte, so dass die Berechnung ab dem Jahr 2100 fehlerhaft war. "Mehr Ehre in der Verletzung als in der Einhaltung" ist ein Satz, der leicht in den Sinn kommt.
Und tatsächlich ist es das. Heutzutage basieren mehrere Systeme auf dieser Interpretation von Bibliotheksroutinen, die von Arthur David Olson geschrieben wurden und die die berüchtigte "Olson-Zeitzonen-Datenbank" konsultieren, die normalerweise in Datenbankdateien unter verschlüsselt ist /usr/share/zoneinfo/
. Das Olson-System hatte zwei Modi:
- Die "Sekunden seit der Epoche" des Kernels werden als UTC-Sekunden seit 1970-01-01 00:00:00 UTC gezählt, mit Ausnahme von Schaltsekunden. Hierbei werden die
posix/
Olson-Zeitzonen-Datenbankdateien verwendet. Alle Tage haben 86400 Kernel-Sekunden und es gibt nie 61 Sekunden in einer Minute, aber sie haben nicht immer die Länge einer SI-Sekunde und die Kernel-Uhr muss gedreht oder gestuft werden, wenn Schaltsekunden auftreten.
- Die "Sekunden seit der Epoche" des Kernels werden als TAI-Sekunden seit 1970-01-01 00:00:10 TAI gezählt. Hierbei werden die
right/
Olson-Zeitzonen-Datenbankdateien verwendet. Die Kernel-Sekunden sind 1 SI Sekunde lang und die Kernel-Uhr muss nie gedreht oder verschoben werden, um Schaltsekunden einzustellen. Die Ausfallzeiten können jedoch Werte wie 23:59:60 annehmen, und die Tage sind nicht immer 86400 Kernel-Sekunden lang.
M. Bernstein hat mehrere Tools geschrieben, einschließlich seines Tool-Sets daemontools
, die erforderlich sind, right/
weil sie einfach 10 hinzugefügt haben time_t
, um TAI-Sekunden seit 1970-01-01 00:00:00 TAI zu erhalten. Er hat dies auf der Handbuchseite dokumentiert.
Diese Anforderung wurde (vielleicht unwissentlich) von Toolsets wie daemontools-encore
und runit
und von Felix von Leitner übernommen libowfat
. Verwenden Sie beispielsweise Bernsteinmultilog
, Guentermultilog
oder Papesvlogd
mit einer Olson- posix/
Konfiguration, und alle TAI64N-Zeitstempel liegen (zum Zeitpunkt der Erstellung dieses Dokuments ) 26 Sekunden hinter der tatsächlichen TAI-Sekundenanzahl seit 1970-01-01 00:00:10 TAI.
Laurent Bercot und ich haben dies in s6 und nosh angesprochen, obwohl wir unterschiedliche Ansätze gewählt haben. M. Bercots basiert tai_from_sysclock()
auf einem Flag zur Kompilierungszeit. nosh - Tools , die viel in TAI64N Blick auf die TZ
und TZDIR
Umgebungsvariablen automatisch erkennen posix/
und right/
wenn sie können.
Interessanterweise enthält FreeBSD Dokumente time2posix()
und posix2time()
Funktionen, die das Äquivalent des Olson- right/
Modus mit time_t
TAI-Sekunden ermöglichen. Sie sind jedoch anscheinend nicht aktiviert.
Noch einmal…
Die UNIX-Zeit wird auf Ihrem Computer mit UNIX durch Oszillatoren gemessen, die in der Hardware Ihres Computers enthalten sind. SI-Sekunden werden nicht verwendet. es ist nicht UTC, obwohl es ihm oberflächlich ähnelt; und es erlaubt absichtlich , dass Ihre Uhr falsch ist.
Weitere Lektüre