Différence entre CLOCK_REALTIME et CLOCK_MONOTONIC?

206

Pourriez-vous expliquer la différence entre CLOCK_REALTIMEet les CLOCK_MONOTONIChorloges renvoyées par clock_gettime()sous Linux?

Quel est le meilleur choix si j'ai besoin de calculer le temps écoulé entre les horodatages produits par une source externe et l'heure actuelle?

Enfin, si j'ai un démon NTP qui ajuste périodiquement l'heure système, comment ces ajustements interagissent-ils avec chacun de CLOCK_REALTIMEet CLOCK_MONOTONIC?

NPE
la source

Réponses:

238

CLOCK_REALTIMEreprésente la meilleure estimation de la machine quant à l'horloge murale actuelle, l'heure de la journée. Comme le disent Ignacio et MarkR , cela signifie que cela CLOCK_REALTIMEpeut sauter en avant et en arrière lorsque l'horloge du système est modifiée, y compris par NTP.

CLOCK_MONOTONICreprésente le temps absolu d'horloge murale écoulé depuis un point fixe arbitraire dans le passé. Il n'est pas affecté par les modifications de l'horloge du système.

Si vous souhaitez calculer le temps écoulé entre deux événements observés sur la même machine sans redémarrage intermédiaire, CLOCK_MONOTONICc'est la meilleure option.

Notez que sous Linux, CLOCK_MONOTONICne mesure pas le temps passé en suspension, bien que selon la définition POSIX il le devrait. Vous pouvez utiliser le spécifique CLOCK_BOOTTIMEà Linux pour une horloge monotone qui continue de fonctionner pendant la suspension.

caf
la source
11
Notez que sur les noyaux plus récents, CLOCK_MONOTONIC_RAW est disponible, ce qui est encore mieux (aucun ajustement NTP).
Joseph Garvin
14
@JosephGarvin pour une certaine valeur de "mieux", peut-être - CLOCK_MONOTONIC_RAW peut fonctionner rapidement ou lentement en temps réel de plusieurs (ou plusieurs centaines) parties par million, et son taux peut varier en raison de conditions environnementales comme la température ou la tension (ou le vol de temps sur machines virtuelles). Sur une machine qui fonctionne correctement, NTP fait de son mieux pour atténuer tous ces facteurs et donc CLOCK_MONOTONIC reflète plus fidèlement le temps réel écoulé.
hobbs
23
Certes, il pourrait être intéressant d'avoir un CLOCK_MONOTONIC_PARBOILED qui a été affecté par les efforts de NTP pour corriger les erreurs de fréquence, mais pas affecté par ses efforts pour corriger les erreurs de phase, mais c'est beaucoup de complexité pour un gain douteux :)
hobbs
1
J'aime le point soulevé par @hobbs. Et si vous vous inquiétez des programmes qui peuvent être affectés par la dérive de l'horloge? Serait CLOCK_MONOTONICle meilleur choix dans ce scénario? Ex: Patriot Missile System
sjagr
3
Je pense qu'il est également important de mentionner que CLOCK_REALTIME est affecté par les secondes intercalaires. Cela signifie qu'il va produire deux horodatages chaque fois qu'un saut de seconde est inséré. La dernière fois, cela s'est produit le 30 juin 2012 et beaucoup de logiciels ont rencontré des problèmes .
user1202136
38

Le livre de Robert Love, LINUX System Programming 2nd Edition , répond spécifiquement à votre question au début du chapitre 11, p. 363:

L'aspect important d'une source de temps monotone n'est PAS la valeur actuelle, mais la garantie que la source de temps augmente strictement linéairement, et donc utile pour calculer la différence de temps entre deux échantillonnages

Cela dit, je pense qu'il suppose que les processus s'exécutent sur la même instance d'un système d'exploitation, donc vous voudrez peut-être exécuter un étalonnage périodique pour pouvoir estimer la dérive.

user2548100
la source
25

CLOCK_REALTIMEest affecté par NTP, et peut avancer et reculer. CLOCK_MONOTONICn'est pas, et avance à un tick par tick.

Ignacio Vazquez-Abrams
la source
15
CLOCK_MONOTONIC est affecté par l'ajustement de l'heure de NTP (rotation de l'heure). Il ne sautera cependant pas.
derobert
3
Mais sur les noyaux plus récents, il y a CLOCK_MONOTONIC_RAW, qui n'est vraiment pas affecté par NTP.
Joseph Garvin
1
"tick" - une idée approximative de la taille / longueur / instructions CPU est un tick sur Linux / amd64? Ou où puis-je obtenir des documents sur tout cela?
kevinarpe
@kevinarpe Pas sûr mais je pense qu'une tique est définie comme une fraction de temps, pas un nombre de cycle CPU, souvent c'est 1/100 de seconde.
Stéphane
@ Stéphane: Je dois sûrement être plus serré que 10 ms. Je pense que Java System.nanoTime()utilise CLOCK_MONOTONICet peut mesurer des durées de 1000ns ou moins. Vous pensez peut-être à l'heure système, qui est parfois limitée à des millisecondes?
kevinarpe
20

En plus de la réponse d' Ignacio , CLOCK_REALTIMEpeut monter en avant par bonds, et parfois en arrière. CLOCK_MONOTONICne fait ni l'un ni l'autre; il continue à avancer (bien qu'il se réinitialise probablement au redémarrage).

Une application robuste doit pouvoir tolérer des CLOCK_REALTIMEsauts en avant de temps en temps (et peut-être en arrière très légèrement très occasionnellement, bien que ce soit plus un cas de bord).

Imaginez ce qui se passe lorsque vous suspendez votre ordinateur portable - CLOCK_REALTIMEsaute en avant après la reprise, CLOCK_MONOTONICnon. Essayez-le sur une machine virtuelle.

MarkR
la source
3
CLOCK_MONOTONIC commence à 0 lorsque le programme démarre; ce n'est pas pour une utilisation interprocessus.
Benubird
18
@Benubird: il ne démarre pas à 0 lorsque le programme démarre. Voilà CLOCK_PROCESS_CPUTIME_ID. Test rapide: $ perl -w -MTime::HiRes=clock_gettime,CLOCK_MONOTONIC -E 'say clock_gettime(CLOCK_MONOTONIC)'-> 706724.117565279. Ce nombre correspond à la disponibilité du système sous Linux, mais la norme dit que c'est arbitraire.
derobert
4
Soit dit en passant, je ne crois pas que le comportement Linux où CLOCK_MONOTONICs'arrête une suspension / reprise est conforme à POSIX. Il est censé être le temps écoulé depuis un point fixe dans le passé, mais l'arrêt de l'horloge en cas de suspension / reprise le rompt.
caf
15

POSIX 7 citations

POSIX 7 spécifie les deux sur http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html :

CLOCK_REALTIME:

Cette horloge représente l'horloge mesurant le temps réel pour le système. Pour cette horloge, les valeurs renvoyées par clock_gettime () et spécifiées par clock_settime () représentent la durée (en secondes et nanosecondes) depuis l'époque.

CLOCK_MONOTONIC (fonctionnalité optionnelle):

Pour cette horloge, la valeur renvoyée par clock_gettime () représente la durée (en secondes et nanosecondes) depuis un point non spécifié dans le passé (par exemple, l'heure de démarrage du système ou l'Epoch). Ce point ne change pas après l'heure de démarrage du système. La valeur de l'horloge CLOCK_MONOTONIC ne peut pas être définie via clock_settime ().

clock_settime()donne un indice important: les systèmes POSIX sont capables de changer arbitrairement CLOCK_REALITMEavec lui, donc ne vous fiez pas à ce qu'il coule ni en continu ni en avant. NTP pouvait être implémenté en utilisant clock_settime()et ne pouvait qu'affecter CLOCK_REALITME.

L'implémentation du noyau Linux semble prendre le temps de démarrage comme l'époque pour CLOCK_MONOTONIC: Point de départ pour CLOCK_MONOTONIC

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
0

Désolé, aucune réputation pour ajouter ceci en tant que commentaire. C'est donc une réponse complémentaire.

En fonction de la fréquence à laquelle vous appelez clock_gettime(), vous devez garder à l'esprit que seules certaines des "horloges" sont fournies par Linux dans le VDSO (c'est-à-dire ne nécessitent pas d'appel système avec tous les frais généraux d'un - ce qui n'a fait qu'empirer lorsque Linux a été ajouté les défenses pour se protéger contre les attaques de type Spectre).

Alors que clock_gettime(CLOCK_MONOTONIC,...), clock_gettime(CLOCK_REALTIME,...)et gettimeofday()vont toujours être extrêmement rapides (accélérés par le VDSO), cela n'est pas vrai pour, par exemple CLOCK_MONOTONIC_RAW ou l'une des autres horloges POSIX.

Cela peut changer avec la version et l'architecture du noyau.

Bien que la plupart des programmes n'aient pas besoin de prêter attention à cela, il peut y avoir des pointes de latence dans les horloges accélérées par le VDSO: si vous les frappez juste lorsque le noyau met à jour la zone de mémoire partagée avec les compteurs d'horloge, il doit attendre le noyau pour terminer.

Voici la "preuve" (GitHub, pour éloigner les bots de kernel.org): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7

anonyme
la source
0

CLOCK_REALTIME : Heure absolue (par exemple 07/01/2020)

CLOCK_MONOTONIC: Temps relatif (par exemple 5 secondes à partir de maintenant ou 10 minutes auparavant)

Bitate
la source