システム時間とRTCを次の値に設定しました。
date -s 2021.08.30-09:59:30 >/dev/null 2>/dev/null //set system time
hwclock -w //sync RTC to system time
また、/etc/TZ( の /etc/localtime と同じファイルbusybox
) は次のように保存されます。
LMT0:00LMT-1:00,M5.5.1/10,M8.5.1/10
夏時間は5月の最終月曜日の午前10時に適用され、8月の最後の月曜日の午前10時に終了します。
システムの動作を観察するために、意図的にシステム時間とRTCをDST終了日の30秒前に設定しました。
DSTが終了したら、システム時間(またはRTC?)を1時間減らす必要があります。
結果は次のとおりです。システム時間とRTCの両方が減少したのではなく、システム時間だけが1時間減少したことは明らかです。
~ # cat /etc/TZ
LMT0:00LMT-1:00,M5.5.1/10,M8.5.1/10
~ # date -s 2021.08.30-09:59:30 >/dev/null 2>/dev/null
~ # hwclock -w
~ #
~ # date
Mon Aug 30 09:59:36 LMT 2021
~ # hwclock
Mon Aug 30 09:59:42 2021 0.000000 seconds
~ #
~ #
~ # date
Mon Aug 30 09:59:49 LMT 2021
~ # hwclock
Mon Aug 30 09:59:53 2021 0.000000 seconds
~ # date
Mon Aug 30 09:00:00 LMT 2021
~ # hwclock
Mon Aug 30 10:00:03 2021 0.000000 seconds
~ # date
Mon Aug 30 09:00:05 LMT 2021
~ # hwclock
Mon Aug 30 10:00:06 2021 0.000000 seconds
しかし、一方で異なる動作します!今回は夏時間の進入時にシステムの動作を観察したかったです。
/etc/TZ は次のように保存されます。
LMT0:00LMT-1:00,M8.5.1/10,M12.5.1/10
夏時間は8月の最終月曜日の午前10時に適用され、12月の最後の月曜日の午前10時に終了します。
また、システム時間とRTCを次の値に設定しました。
date -s 2021.08.30-09:59:30 >/dev/null 2>/dev/null //set system time
hwclock -w //sync RTC to system time
DSTが適用されたら、システム時間(またはRTC?)を1時間先に追加する必要があります。
結果は次のとおりです。システム時間とRTCが1時間増加したことは明らかです。
~ # cat /etc/TZ
LMT0:00LMT-1:00,M8.5.1/10,M12.5.1/10
~ # date -s 2021.08.30-09:59:30 >/dev/null 2>/dev/null
~ # hwclock -w
~ #
~ # date
Mon Aug 30 09:59:35 LMT 2021
~ # hwclock
Mon Aug 30 09:59:37 2021 0.000000 seconds
~ # date
Mon Aug 30 09:59:48 LMT 2021
~ # hwclock
Mon Aug 30 09:59:51 2021 0.000000 seconds
~ # date
Mon Aug 30 11:00:04 LMT 2021
~ # hwclock
Mon Aug 30 11:00:06 2021 0.000000 seconds
なぜこのような矛盾した動作が発生するのか疑問に思います。
答え1
hwclock
レジスタのハードウェアクロックの正確な値は何だと思いますか?
そうではありません。
証明する:
# date; hwclock; TZ=UTC hwclock; grep rtc_time /proc/driver/rtc
Wed 1 Sep 18:33:18 EEST 2021
2021-09-01 18:33:18.870798+03:00
2021-09-01 15:33:18.981738+00:00
rtc_time : 15:33:20
hwclock
との出力がどのように表示されるかを確認してくださいTZ=UTC hwclock
。
hwclock
ハードウェア時計の値を表示します。必要に応じて現在のタイムゾーンに変換します(DSTオフセットとタイムゾーンを含む)。。生の値を表示するには、以下を使用する必要がありますcat /proc/driver/rtc
。システムがクラシックPC CMOSクロックドライバ、UEFIクロックインターフェイス、または他のリアルタイムクロックドライバを使用しているかどうかに応じて、このドライバは(またはtime_t
)time64_t
およびクロック設定プロセスに戻ります。
norオプションはハードウェアクロックの取得または設定にも使用されないため、ハードウェアクロック--utc
のローカル/ UTCステータスはファイルの3行目(存在する場合)によって決まります--local
。/etc/adjtime
最初のテストでは、DSTが適用されたときにハードウェアクロックを設定するため、UTCオフセットは-1(UTC =ローカル-1時間)です。ハードウェア時計が現地時間を使用するように設定されている場合は、予想通り09:59:30に設定されます。
ただし、ハードウェアクロックがUTCを使用するように設定されている場合、クロックレジスタに設定された実際の値は次のようになります。08:59:30。 DST切り替え前の時計を見ると、このオフセットが自動的に検出されるため、hwclock
予想される09:59:**が表示されます。
DST 遷移が発生すると、ハードウェアクロックが現地時間に設定されている場合、クロックレジスタは 10:00:00 の値に増加します。現在は現地時間でDSTオフセットは0なので、10:00: hwclock
00と表示されます。
ただし、ハードウェアクロックがUTC時間に設定されている場合、クロックレジスタの値は09:00:00になります。 DST変換後のUTCオフセットは0になるため、09:00: hwclock
00とも表示されます。
オペレーティングシステムの時計は常に内部的にUTCで実行され、タイムゾーン+ DSTルールに従ってローカル時間に変換されるため、予想どおり09:00:00(DSTではありません)として表示されます。
hwclock
ここで得られた結果は10:00:00なので、ファイルの3行目にが表示される/etc/adjtime
はずですLOCAL
。
2番目のテストでは、DSTが無効になったときにクロックを設定するため、合計UTCオフセットは0になります。 UTCを有効にしても現地時間を使用しても、クロックレジスタは09:59:30に設定されます。以前のテストでは現地時間に設定されていることがわかります。
DST切替時間が到来すると、ハードウェアクロックレジスタは10:00:00...を読み込み、レジスタ値は現在のタイムゾーンに従ってフォーマットされて表示されるため、問題があります。有効なタイムゾーンルールによると今日の現地時間10:00:00には存在しません!
DST変換のため、この特定の日付には、現地時間の10:00:00値を表すことができるUTCタイムスタンプ値はありません。 09:59:59 UTCは現地時間09:59:59ですが、10:00です。 :00 UTCは現地時間11:00:00です。時間値glibc
このタイムゾーン変換および書式設定ルーチンを経ると、存在しない10:00:00が11:00:00にプッシュされます。
したがって、DSTを標準時間に変換して最初の1時間ハードウェアクロックを照会すると、hwclock
時間を誤って伝えることができるクロックレジスタの実際の値は、有効な現地時間値として表示できないためです。これは表示アーティファクトにすぎません。/proc/driver/rtc
この魔法のような瞬間にも正しい値が表示され続けるはずです。
これは、ハードウェア時計を現地時間に設定した場合に発生する可能性があるすべての予期しない問題の良い例です。
リンクで仕上げますTom Scottのコンピュータタイミングに関する10分間のYouTube動画は非常に適しています。結論を高く評価すると思います。