Ich glaube, Sie wollen clock_gettime
mit CLOCK_TAI
richtig zu arbeiten. Ich auch.
Der kritische Satz in der referenzierten Antwort lautet:"Bitte beachten Sie, dass der Offset von CLOCK_REALTIME beim Booten auf Null initialisiert wird und weder ntpd noch chronyd ihn standardmäßig auf den richtigen Wert setzen (derzeit 35)."
Dies mag immer noch wahr sein, abgesehen davon, dass der Offset jetzt 37 beträgt, aber ein neuerer ntpd kann zumindest so konfiguriert werden, dass er den Offset setzt. Ich habe Folgendes auf einem openSUSE-Rechner gemacht:
vi /etc/ntp.conf # Add the line: leapfile /var/lib/ntp/etc/ntp.leapseconds
update-leap
service ntpd restart
less /var/log/ntp # Check for errors
Dann clock_gettime(CLOCK_TAI, &res)
schien richtig zu funktionieren.
Ich denke, dass ntp den Offset mit ntp_adjtime
setzt mit MOD_TAI
. Durchsuchen der Chrony-Quelle mit grep -P '(ADJ|MOD)_TAI'
findet keine Übereinstimmungen, also scheint Chrony diese Fähigkeit noch nicht zu haben.
Sie können libtai
verwenden von djb:https://cr.yp.to/libtai.html
Was ist das?
libtai ist eine Bibliothek zum Speichern und Bearbeiten von Daten und Zeiten.
libtai unterstützt zwei Zeitskalen:(1) TAI64, das einige hundert Milliarden Jahre mit einer Genauigkeit von 1 Sekunde abdeckt; (2) TAI64NA, deckt denselben Zeitraum mit einer Genauigkeit von 1 Attosekunde ab. Beide Skalen sind in Bezug auf TAI, den aktuellen internationalen Echtzeitstandard, definiert.
libtai bietet ein internes Format für TAI64, struct tai, das für schnelle Zeitmanipulationen entwickelt wurde. Die Routinen tai_pack() und tai_unpack() konvertieren zwischen struct tai und einem portablen 8-Byte-TAI64-Speicherformat. libtai bietet ähnliche interne und externe Formate für TAI64NA.
libtai bietet struct caldate zum Speichern von Datumsangaben in Jahr-Monat-Tag-Form. Es kann struct caldate nach dem gregorianischen Kalender in eine modifizierte julianische Tageszahl für eine einfache Datumsarithmetik umwandeln.
libtai stellt struct caltime bereit, um Kalenderdaten und -zeiten zusammen mit UTC-Offsets zu speichern. Es kann von struct tai in struct caltime in UTC konvertieren, wobei Schaltsekunden berücksichtigt werden, um eine genaue Datums- und Zeitanzeige zu ermöglichen. Es kann auch für Benutzereingaben von struct caltime in struct tai zurückkonvertieren. Seine Gesamtumwandlungsgeschwindigkeit von UTC zu TAI ist 100-mal besser als die übliche UNIX mktime()-Implementierung.
Diese Version von libtai erfordert ein UNIX-System mit gettimeofday(). Mit Compilern, die 64-Bit-Arithmetik unterstützen, wird es einfach sein, auf andere Betriebssysteme zu portieren.
Der Quellcode von libtai ist gemeinfrei.
Da ich chrony
ausführe anstelle des alten ntpd
, hatte ich keinen automatisierten Weg, um die Kernel-Parameter richtig hinzubekommen, also habe ich nach einer Alternative gesucht.
Da der Offset zwischen TAI und UTC relativ konstant ist (ändert sich
Es gibt eine Testanwendung zum Setzen des Kernel-Offsets in den Kernel-Quellen, in
Ich habe die Kernel-Testanwendung heruntergeschnitten, sodass die Hauptanwendung zu:
Dann ging es für meinen Anwendungsfall nur noch darum, den richtigen Wert aus
Hoffe, das ist für jemand anderen nützlich!tools/testing/selftests/timers/set-tai.c
. Und vorausgesetzt, Sie haben den tzdata
Paket installiert, gibt es eine Datei mit dem Offset zwischen UTC und TAI in /usr/share/zoneinfo/leap-seconds.list
.int main(int argc, char **argv)
{
int i, ret;
ret = get_tai();
printf("tai offset started at %i\n", ret);
if (argc < 2)
{
printf("New offset not given, not setting\n");
}
else
{
i = strtol(argv[1],NULL,10);
printf("Attempting to set TAI offset to %d\n",i);
printf("Checking tai offsets can be properly set: ");
ret = set_tai(i);
ret = get_tai();
if (ret != i) {
printf("[FAILED] expected: %i got %i\n", i, ret);
return EXIT_FAILURE;
}
}
printf("[OK]\n");
return EXIT_SUCCESS;
}
leap-seconds.list
zu extrahieren Datei und Ausführen von set-tai
mit diesem als Parameter (in /etc/rc.local
damit es beim Booten passiert). Ein Beispiel dafür ist:TAI_OFFSET=$(grep -v '^#' /usr/share/zoneinfo/leap-seconds.list | tail -1 | awk '{ print $2 }')
if [ -x /usr/local/sbin/set-tai ]; then
/usr/local/sbin/set-tai $TAI_OFFSET
fi