Differenza tra CLOCK_REALTIME e CLOCK_MONOTONIC?


206

Potresti spiegare la differenza tra CLOCK_REALTIMEe gli CLOCK_MONOTONICorologi restituiti clock_gettime()su Linux?

Qual è la scelta migliore se devo calcolare il tempo trascorso tra i timestamp prodotti da una fonte esterna e l'ora corrente?

Infine, se ho un demone NTP che regola periodicamente l'ora del sistema, in che modo queste regolazioni interagiscono con ciascuna di CLOCK_REALTIMEe CLOCK_MONOTONIC?

Risposte:


238

CLOCK_REALTIMErappresenta la migliore ipotesi della macchina per quanto riguarda l'orologio da parete attuale, l'ora del giorno. Come dicono Ignacio e MarkR , ciò significa che CLOCK_REALTIMEpuò saltare avanti e indietro quando l'orologio del sistema viene modificato, incluso da NTP.

CLOCK_MONOTONICrappresenta il tempo di orologio da parete trascorso in assoluto da un punto fisso arbitrario nel passato. Non è influenzato dai cambiamenti nell'orologio del sistema.

Se si desidera calcolare il tempo trascorso tra due eventi osservati su una macchina senza un riavvio intermedio, CLOCK_MONOTONICè l'opzione migliore.

Si noti che su Linux, CLOCK_MONOTONICnon misura il tempo trascorso in sospensione, anche se per definizione POSIX dovrebbe. È possibile utilizzare lo specifico di Linux CLOCK_BOOTTIMEper un orologio monotonico che continua a funzionare durante la sospensione.


11
Si noti che sui kernel più recenti, CLOCK_MONOTONIC_RAW è disponibile, il che è ancora migliore (nessuna regolazione NTP).
Joseph Garvin,

14
@JosephGarvin per un certo valore di "migliore", forse - CLOCK_MONOTONIC_RAW potrebbe funzionare veloce o lento del tempo reale di diverse (o diverse centinaia) parti per milione e la sua velocità potrebbe variare a causa di condizioni ambientali come temperatura o tensione (o rubare il tempo macchine virtuali). Su una macchina che funziona correttamente, NTP fa del suo meglio per mitigare tutti questi fattori e quindi CLOCK_MONOTONIC riflette più da vicino il vero tempo trascorso.
Hobbs,

23
Certo, potrebbe essere interessante avere un CLOCK_MONOTONIC_PARBOILED che è stato influenzato dagli sforzi di NTP per correggere gli errori di frequenza, ma non è stato influenzato dai suoi sforzi per correggere gli errori di fase, ma è molto complesso per un guadagno dubbio :)
hobbs

1
Mi piace il punto che @hobbs solleva. E se ti preoccupi dei programmi che possono essere influenzati dalla deriva dell'orologio? Sarebbe CLOCK_MONOTONICla scelta migliore in quello scenario? ad es. Patriot Missile System
sjagr

3
Penso che sia anche importante ricordare che CLOCK_REALTIME è influenzato dai secondi saltati. Ciò significa che sarà produrre doppia timestamp ogni volta che viene inserito un secondo salto. L'ultima volta è successo il 30 giugno 2012 e molti software hanno avuto problemi .
user1202136

38

Il libro LINUX System Programming 2nd Edition di Robert Love , affronta in modo specifico la tua domanda all'inizio del capitolo 11, pag. 363:

L'aspetto importante di una sorgente di tempo monotona NON è il valore corrente, ma la garanzia che la sorgente di tempo sia strettamente lineare in modo lineare, e quindi utile per calcolare la differenza di tempo tra due campionamenti

Detto questo, credo che stia supponendo che i processi siano in esecuzione sulla stessa istanza di un sistema operativo, quindi potresti voler eseguire una calibrazione periodica per poter stimare la deriva.


25

CLOCK_REALTIMEè interessato da NTP e può spostarsi avanti e indietro. CLOCK_MONOTONICnon lo è e avanza di un tick per tick.


15
CLOCK_MONOTONIC è influenzato dalla regolazione dell'ora NTP (rotazione oraria). Non salterà, tuttavia.
derobert,

3
Ma sui kernel più recenti c'è CLOCK_MONOTONIC_RAW, che in realtà non è influenzato da NTP.
Joseph Garvin,

1
"tick" - qualche idea approssimativa di quanto siano grandi / lunghe / istruzioni CPU un tick su Linux / amd64? O dove posso ottenere documenti su uno di questi?
Kevinevpe il

@kevinarpe Non sono sicuro ma penso che un tick sia definito come una frazione di tempo, non un numero di cicli della CPU, spesso è 1/100 di secondo.
Stéphane

@ Stéphane: devo sicuramente essere più stretto di 10ms. Penso che gli System.nanoTime()usi di Java CLOCK_MONOTONICe possano misurare durate di 1000 n o meno. Forse stai pensando al tempo di sistema, che a volte è limitato a millisecondi?
kevinarpe,

20

Oltre alla risposta di Ignacio , CLOCK_REALTIMEpuò salire in avanti a passi da gigante, e occasionalmente all'indietro. CLOCK_MONOTONICnon fa nessuno dei due; continua ad andare avanti (anche se probabilmente si ripristina al riavvio).

Un'app robusta deve essere in grado di tollerare CLOCK_REALTIMEsaltando in avanti di tanto in tanto (e forse all'indietro molto leggermente molto occasionalmente, sebbene sia più un caso limite).

Immagina cosa succede quando sospendi il tuo laptop - i CLOCK_REALTIMEsalti in avanti dopo il curriculum CLOCK_MONOTONICnon lo fanno. Provalo su una VM.


3
CLOCK_MONOTONIC inizia da 0 all'avvio del programma; non è per uso tra processi.
Benubird,

18
@Benubird: non parte da 0 all'avvio del programma. Questo è CLOCK_PROCESS_CPUTIME_ID. Test rapido: $ perl -w -MTime::HiRes=clock_gettime,CLOCK_MONOTONIC -E 'say clock_gettime(CLOCK_MONOTONIC)'-> 706724.117565279. Quel numero corrisponde al tempo di attività del sistema su Linux, ma lo standard dice che è arbitrario.
derobert,

4
A parte questo, non credo che il comportamento di Linux in cui si CLOCK_MONOTONICferma su una sospensione / ripresa sia conforme a POSIX. Dovrebbe essere il tempo trascorso da un punto fisso nel passato, ma fermare l'orologio per sospendere / riprendere lo rompe.
Caf

15

Virgolette POSIX 7

POSIX 7 specifica entrambi su http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html :

CLOCK_REALTIME:

Questo orologio rappresenta l'orologio che misura il tempo reale per il sistema. Per questo orologio, i valori restituiti da clock_gettime () e specificati da clock_settime () rappresentano la quantità di tempo (in secondi e nanosecondi) dall'epoca.

CLOCK_MONOTONIC (funzione opzionale):

Per questo orologio, il valore restituito da clock_gettime () rappresenta la quantità di tempo (in secondi e nanosecondi) da un punto non specificato in passato (ad esempio, tempo di avvio del sistema o epoca). Questo punto non cambia dopo il tempo di avvio del sistema. Il valore dell'orologio CLOCK_MONOTONIC non può essere impostato tramite clock_settime ().

clock_settime()dà un suggerimento importante: i sistemi POSIX sono in grado di cambiare arbitrariamente CLOCK_REALITMEcon esso, quindi non fare affidamento sul suo flusso né continuo né in avanti. NTP potrebbe essere implementato usandoclock_settime() e può solo influenzare CLOCK_REALITME.

L'implementazione del kernel Linux sembra impiegare il tempo di avvio come epoca per CLOCK_MONOTONIC: Punto di partenza per CLOCK_MONOTONIC


0

Siamo spiacenti, non è una reputazione aggiungere questo come commento. Quindi va come una risposta complementare.

A seconda di quanto spesso chiamerai clock_gettime(), tieni presente che solo alcuni degli "orologi" sono forniti da Linux nel VDSO (cioè non richiedono un syscall con tutto il sovraccarico di uno - che peggiora solo quando Linux aggiunge le difese da proteggere dagli attacchi di tipo Spettro).

Mentre clock_gettime(CLOCK_MONOTONIC,...), clock_gettime(CLOCK_REALTIME,...)e gettimeofday()saranno sempre estremamente veloci (accelerati dal VDSO), non lo è vero, ad esempio CLOCK_MONOTONIC_RAW o uno qualsiasi degli altri orologi POSIX.

Questo può cambiare con la versione del kernel e l'architettura.

Sebbene la maggior parte dei programmi non debba prestare attenzione a questo, ci possono essere picchi di latenza negli clock accelerati dal VDSO: se li colpisci nel momento in cui il kernel aggiorna l'area di memoria condivisa con i contatori di clock, deve attendere che il kernel per finire.

Ecco la "prova" (GitHub, per tenere i bot lontani da kernel.org): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7


0

CLOCK_REALTIME : Tempo assoluto (ad es. 07/01/2020)

CLOCK_MONOTONIC: Tempo relativo (ad es. 5 secondi da oggi o 10 minuti fa)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.