Sep 272012
 

Il y a deux horloges principales dans un système Linux :

L’horloge machine : Il s’agit de l’horloge utilisant un quartz dédié (généralement identique à ceux d’une montre bracelet) Cette horloge fonctionne d’une manière indépendante des programmes et même lorsque la machine est éteinte. elle a une précision de l’ordre de la seconde.
A divers endroits cette horloge est communément appelée l’horloge machine (« hardware clock »), l’heure temps réelle (« real time clock »), le RTC, l’horloge BIOS ou l’horloge CMOS.

L’horloge système : C’est l’horloge gérée par le noyau Linux et contrôlée par un timer. (Attention, Linux peut utiliser plusieurs clocksource différentes selon la configuration)
L’heure système est le nombre de secondes écoulées depuis Epoch (le 1er janvier 1970 00:00:00 UTC)
L’heure système est initialisée avec la valeur de l’horloge machine au démarrage de Linux, l’horloge machine n’est ensuite plus utilisée.
Le timestamp unix a la structure suivante :
struct timeval {
time_t tv_sec; /* secondes */
suseconds_t tv_usec; /* microsecondes */
};

On peut remarquer que le timestamp est toujours UTC. C’est seulement au moment de l’affichage que l’on calcule la date et l’heure locale en tenant compte de la timezone (fuseau horaire plus ajustement heure d’été/d’hiver). Attention la timezone est une variable d’environnement et un ensemble de règles du paquet tzdata. Il existe une structure timezone historique qui est obsolète

struct timezone {
int tz_minuteswest; /* minutes à l'ouest de Greenwich */
int tz_dsttime; /* type de changement horaire */
};

l’argument tz doit en général être NULL. Le champ tz_dsttime n’a jamais été utilisé sous Linux, il n’a jamais été géré, et ne le sera jamais par la libc ou glibc.

la fonction gettimeofday() retourne le timestamp.

Historiquement le timestamp est 32bits () mais sur debian squeeze 64 bits
sizeof time_t = 8
sizeof suseconds_t = 8

Ce sont donc « déjà » des entiers 64 bits signés.

Pour corriger la dérive de l’horloge, il existe une fonction adjtime() qui ajuste graduellement l’horloge système en l’accélérant ou la ralentissant à un rythme constant de 0.5ms/s.
int adjtime(const struct timeval *delta, struct timeval *olddelta);
si delta est NULL olddelta est peuplé avec le temps à ajuster restant.

La commande ntpdate utilise adjtime() si l’écart entre l’horloge locale et l’horloge de référence est inférieur à +-128 ms. Cela permet de recaler l’horloge tout en gardant un timestamp monotone. (qui ne reviens jamais en arrière et sans saut dans le futur) Au delà, comme il faudrait plus de 5 minutes pour recaler l’horloge , celle ci est réglée de façon abrupte.
Tout nouvel appel à adjtime avec un décalage non NULL conserve le décalage déjà effectué mais fait perdre le décalage restant à faire.
L’utilisation de ntpdate pendant la période d’ajustement induit de légères erreurs de mesure du delta à cause du fait que l’horloge est déjà en cours d’accélération ou de ralentissement. Il vaut donc mieux attendre que adjtime ait fini avant de faire à nouveau appel à ntpdate.

Enfin il exite une fonction permettant de modifier de façon permanente la derive de l’horloge soft.
by adjusting the rate at which the system time is advanced with each timer interrupt, using adjtimex(8).

Sorry, the comment form is closed at this time.