Unterschied zwischen CLOCK_REALTIME und CLOCK_MONOTONIC?


206

Können Sie den Unterschied zwischen CLOCK_REALTIMEund unter Linux zurückgegebenen CLOCK_MONOTONICUhren erklären clock_gettime()?

Welches ist die bessere Wahl, wenn ich die verstrichene Zeit zwischen von einer externen Quelle erzeugten Zeitstempeln und der aktuellen Zeit berechnen muss?

Wenn ich einen NTP-Daemon habe, der die Systemzeit regelmäßig anpasst, wie interagieren diese Anpassungen mit jedem von CLOCK_REALTIMEund CLOCK_MONOTONIC?

Antworten:


238

CLOCK_REALTIMEstellt die beste Vermutung der Maschine hinsichtlich der aktuellen Wanduhr und Tageszeit dar. Wie Ignacio und MarkR sagen, bedeutet dies, dass CLOCK_REALTIMEvorwärts und rückwärts gesprungen werden kann, wenn die Uhrzeit des Systems geändert wird, auch durch NTP.

CLOCK_MONOTONICrepräsentiert die absolut verstrichene Wanduhrzeit seit einem beliebigen festen Punkt in der Vergangenheit. Es ist nicht von Änderungen der Systemzeituhr betroffen.

Wenn Sie die verstrichene Zeit zwischen zwei auf einem Computer beobachteten Ereignissen ohne einen dazwischen liegenden Neustart berechnen möchten, CLOCK_MONOTONICist dies die beste Option.

Beachten Sie, dass unter Linux CLOCK_MONOTONICdie in Suspend verbrachte Zeit nicht gemessen wird, obwohl dies nach der POSIX-Definition der Fall sein sollte. Sie können Linux-spezifisch CLOCK_BOOTTIMEfür eine monotone Uhr verwenden, die während des Suspendierens weiterläuft.


11
Beachten Sie, dass auf neueren Kerneln CLOCK_MONOTONIC_RAW verfügbar ist, was sogar noch besser ist (keine NTP-Anpassungen).
Joseph Garvin

14
@JosephGarvin für einen Wert von "besser", vielleicht - CLOCK_MONOTONIC_RAW kann in Echtzeit um mehrere (oder mehrere hundert) Teile pro Million schnell oder langsam laufen, und seine Rate kann aufgrund von Umgebungsbedingungen wie Temperatur oder Spannung (oder Diebstahlzeit) variieren virtuelle Maschinen). Auf einer ordnungsgemäß funktionierenden Maschine bemüht sich NTP, all diese Faktoren zu mindern. Daher spiegelt CLOCK_MONOTONIC die tatsächlich verstrichene Zeit genauer wider .
Hobbs

23
Zugegeben, es könnte interessant sein, ein CLOCK_MONOTONIC_PARBOILED zu haben, das von den Bemühungen von NTP zur Korrektur von Frequenzfehlern betroffen war, aber von den Bemühungen zur Korrektur von Phasenfehlern nicht betroffen war, aber das ist eine Menge Komplexität für einen zweifelhaften Gewinn :)
hobbs

1
Ich mag den Punkt, den @hobbs anspricht. Was ist, wenn Sie sich Sorgen über Programme machen, die von der Taktverschiebung betroffen sein können? Wäre CLOCK_MONOTONICin diesem Szenario die beste Wahl? zB Patriot Missile System
sjagr

3
Ich denke, es ist auch wichtig zu erwähnen, dass CLOCK_REALTIME von Schaltsekunden betroffen ist. Dies bedeutet, dass jedes Mal, wenn eine Schaltsekunde eingefügt wird , doppelte Zeitstempel erzeugt werden. Das letzte Mal geschah dies am 30. Juni 2012 und eine ganze Menge Software geriet in Schwierigkeiten .
user1202136

38

Das Buch LINUX System Programming 2nd Edition von Robert Love befasst sich speziell mit Ihrer Frage zu Beginn von Kapitel 11, S. 363:

Der wichtige Aspekt einer monotonen Zeitquelle ist NICHT der aktuelle Wert, sondern die Garantie, dass die Zeitquelle streng linear ansteigt und daher zur Berechnung der Zeitdifferenz zwischen zwei Abtastungen nützlich ist

Ich glaube jedoch, dass er davon ausgeht, dass die Prozesse auf derselben Instanz eines Betriebssystems ausgeführt werden. Daher möchten Sie möglicherweise eine regelmäßige Kalibrierung durchführen, um die Drift abschätzen zu können.


25

CLOCK_REALTIMEist von NTP betroffen und kann sich vorwärts und rückwärts bewegen. CLOCK_MONOTONICist nicht und rückt mit einem Tick pro Tick vor.


15
CLOCK_MONOTONIC ist von der Zeitanpassung von NTP (Zeitverschiebung) betroffen. Es wird jedoch nicht springen.
Derobert

3
Auf neueren Kerneln gibt es jedoch CLOCK_MONOTONIC_RAW, das von NTP wirklich nicht betroffen ist.
Joseph Garvin

1
"tick" - eine grobe Vorstellung davon, wie groß / lang / CPU-Anweisungen ein Tick unter Linux / amd64 ist? Oder wo kann ich Dokumente dazu bekommen?
Kevinarpe

@kevinarpe Ich bin mir nicht sicher, aber ich denke, ein Tick wird als Bruchteil der Zeit definiert, nicht als Anzahl von CPU-Zyklen, oft sind es 1/100 Sekunden.
Stéphane

@ Stéphane: Ich muss sicher enger als 10ms sein. Ich denke, Java System.nanoTime()verwendet CLOCK_MONOTONICund kann eine Dauer von 1000 ns oder weniger messen . Vielleicht denken Sie über die Systemzeit nach, die manchmal auf Millisekunden beschränkt ist?
Kevinarpe

20

Neben Ignacio Antwort ,CLOCK_REALTIME kann in den Sprüngen nach oben vorwärts und rückwärts hin und wieder. CLOCK_MONOTONICtut beides nicht; es geht einfach weiter vorwärts (obwohl es wahrscheinlich beim Neustart zurückgesetzt wird).

Eine robuste App muss tolerieren können CLOCK_REALTIME gelegentlich vorwärts springen (und möglicherweise gelegentlich sehr leicht rückwärts, obwohl dies eher ein Randfall ist).

Stellen Sie sich vor, was passiert, wenn Sie Ihren Laptop anhalten - CLOCK_REALTIMEspringt nach dem Lebenslauf vorwärts, CLOCK_MONOTONICnicht. Probieren Sie es auf einer VM aus.


3
CLOCK_MONOTONIC startet beim Start des Programms bei 0; Es ist nicht für den Interprozess vorgesehen.
Benubird

18
@ Benubird: Es startet nicht bei 0, wenn das Programm startet. Das ist CLOCK_PROCESS_CPUTIME_ID. Schnelltest: $ perl -w -MTime::HiRes=clock_gettime,CLOCK_MONOTONIC -E 'say clock_gettime(CLOCK_MONOTONIC)'-> 706724.117565279. Diese Zahl entspricht der Systemverfügbarkeit unter Linux, aber der Standard sagt, dass dies willkürlich ist.
Derobert

4
Abgesehen davon glaube ich nicht, dass das Linux-Verhalten, bei dem CLOCK_MONOTONICein Suspend / Resume angehalten wird, POSIX-konform ist. Es sollte die Zeit seit einem festen Punkt in der Vergangenheit sein, aber das Stoppen der Uhr über Suspend / Resume bricht das.
Café

15

POSIX 7 Anführungszeichen

POSIX 7 spezifiziert beide unter http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html :

CLOCK_REALTIME::

Diese Uhr repräsentiert die Uhr, die Echtzeit für das System misst. Für diese Uhr geben die von clock_gettime () zurückgegebenen und von clock_settime () angegebenen Werte die Zeitspanne (in Sekunden und Nanosekunden) seit der Epoche an.

CLOCK_MONOTONIC (optionale Funktion):

Für diese Uhr gibt der von clock_gettime () zurückgegebene Wert die Zeitdauer (in Sekunden und Nanosekunden) seit einem nicht angegebenen Zeitpunkt in der Vergangenheit an (z. B. Systemstartzeit oder Epoche). Dieser Punkt ändert sich nach der Systemstartzeit nicht. Der Wert der Uhr CLOCK_MONOTONIC kann nicht über clock_settime () eingestellt werden.

clock_settime()gibt einen wichtigen Hinweis: POSIX-Systeme können sich damit willkürlich ändern, verlassen CLOCK_REALITMESie sich also nicht darauf, dass es weder kontinuierlich noch vorwärts fließt. NTP konnte mithilfe von implementiert werden clock_settime()und nur Auswirkungen haben CLOCK_REALITME.

Die Implementierung des Linux-Kernels scheint die Startzeit als Epoche für Folgendes zu benötigenCLOCK_MONOTONIC : Startpunkt für CLOCK_MONOTONIC


0

Entschuldigung, kein Ruf, dies als Kommentar hinzuzufügen. Es geht also um eine ergänzende Antwort.

Je nachdem, wie oft Sie anrufen clock_gettime(), sollten Sie berücksichtigen, dass nur einige der "Uhren" von Linux im VDSO bereitgestellt werden (dh Sie benötigen keinen Systemaufruf mit dem gesamten Overhead von einem - was sich nur verschlimmerte, wenn Linux hinzugefügt wurde die Abwehrkräfte zum Schutz vor Spectre-ähnlichen Angriffen).

Während clock_gettime(CLOCK_MONOTONIC,...), clock_gettime(CLOCK_REALTIME,...)und gettimeofday()sind immer extrem schnell sein würde (durch die VDSO beschleunigt), dann ist dies nicht für z. B. CLOCK_MONOTONIC_RAW oder eine der anderen POSIX-Uhren.

Dies kann sich mit der Kernelversion und der Architektur ändern.

Obwohl die meisten Programme dies nicht beachten müssen, kann es zu Latenzspitzen bei Uhren kommen, die vom VDSO beschleunigt werden: Wenn Sie sie direkt treffen, wenn der Kernel den gemeinsam genutzten Speicherbereich mit den Uhrzählern aktualisiert, muss er auf die warten Kernel zu beenden.

Hier ist der "Beweis" (GitHub, um Bots von kernel.org fernzuhalten): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.