私のLinuxマシンはCLOCK_TAI
をサポートしていますが、CLOCK_REALTIME
からのオフセットが誤ってゼロになっています(これがデフォルトです)。 CLOCK_TAI
をTAIとして維持するソフトウェアまたはその他のソリューションはありますか?
回答 ここ と ここ から、ntpd
もchronyd
もこれを行っていないようです。
CLOCK_REALTIME
やgettimeofday
などがPOSIX時間(基本的にUTC)を返す場合、これを実現するためにハードウェアクロックをTAIに設定できれば幸いです。
_clock_gettime
_と_CLOCK_TAI
_を正しく機能させたいと思います。私はやった。
参照された回答の重要な文は次のとおりです。「CLOCK_REALTIMEからのオフセットは起動時にゼロに初期化され、ntpdもchronydもデフォルトで正しい値(現在は35)に設定しないことに注意してください。」
オフセットが現在37であることを除けば、これは依然として当てはまる可能性がありますが、最近のntpdは、少なくともオフセットを設定するように構成できます。私はopenSUSEマシンで次のことを行いました。
_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
_
その後、clock_gettime(CLOCK_TAI, &res)
は正しく機能しているように見えました。
Ntpは_ntp_adjtime
_と_MOD_TAI
_を使用してオフセットを設定すると思います。 grep -P '(ADJ|MOD)_TAI'
でchronyソースを検索しても一致するものが見つからないため、chronyにはまだこの機能がないようです。
古いchrony
の代わりにntpd
を実行しているため、カーネルパラメータを正しく取得する自動化された方法がなかったため、別の方法を検討しました。
TAIとUTCの間のオフセットは比較的一定であるため(1年に1回未満の変更)、カーネルパラメータを静的に設定することが可能であり、アプリケーションでCLOCK_TAIクロックを使用すると正しい値が得られます。
カーネルソースのカーネルオフセットを設定するためのテストアプリケーションがtools/testing/selftests/timers/set-tai.c
にあります。また、tzdata
パッケージがインストールされているとすると、/usr/share/zoneinfo/leap-seconds.list
にUTCとTAIの間にオフセットがあるファイルがあります。
カーネルテストアプリケーションを切り詰めたので、メインは次のようになりました。
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
ファイルから正しい値を抽出し、これをパラメーターとしてset-tai
を実行するだけでした(/etc/rc.local
で)。起動時間)。これを行う方法の例は次のとおりです。
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
これが他の誰かに役立つことを願っています!
Djbからlibtai
を使用できます: https://cr.yp.to/libtai.html
それは何ですか?
libtaiは、日付と時刻を保存および操作するためのライブラリです。
libtaiは2つの時間スケールをサポートします。(1)TAI64、1秒の精度で数千億年をカバーします。 (2)TAI64NA、1アト秒の精度で同じ期間をカバーします。どちらのスケールも、現在の国際的なリアルタイム標準であるTAIで定義されています。
libtaiは、高速時間操作用に設計されたTAI64の内部形式であるstructtaiを提供します。 tai_pack()およびtai_unpack()ルーチンは、structtaiとポータブル8バイトTAI64ストレージ形式の間で変換します。 libtaiは、TAI64NAに同様の内部形式と外部形式を提供します。
libtaiは、日付を年-月-日の形式で格納するための構造体caldateを提供します。グレゴリオ暦の下で構造体caldateを変更されたユリウス日番号に変換して、日付を簡単に計算できます。
libtaiは、UTCオフセットとともにカレンダーの日付と時刻を格納するためのstructcaltimeを提供します。正確な日付と時刻を表示するために、うるう秒を考慮して、UTCでstructtaiからstructcaltimeに変換できます。また、ユーザー入力のためにstructcaltimeからstructtaiに戻すこともできます。その全体的なUTCからTAIへの変換速度は、通常のUNIX mktime()実装よりも100倍優れています。
このバージョンのlibtaiには、gettimeofday()を備えたUNIXシステムが必要です。 64ビット演算をサポートするコンパイラを使用すると、他のオペレーティングシステムに簡単に移植できます。
Libtaiのソースコードはパブリックドメインにあります。