前回記事「Windows で時刻あわせ (5) w32tm (トラブル事例)」はこちら。
【注意と免責】
以下の内容は個人的な見解であり正しさを保証しません。正しさを必要とする場合は他のサイトの記事を参照してください。
閉域のネットワーク環境で。とある Windows 端末を時刻マスターとし、閉域ネットワークに接続されているその他の端末の時刻をその時刻マスターと同期させたい、という要求が稀にあります。
ろくなことにならないので、そのような要求は全力で退けましょう(何
本気でそのような要求があるのであれば、Windows を時刻マスターにするのではなく、タイムサーバー製品の導入を検討しましょう。価格がうん十万円とかしますし、設置(アンテナ等)も面倒ですが・・・(汗
それでもなんとか Windows を時刻マスターにしたいのである、という場合、クリアしないとならない問題があります。
- 時刻マスターとなる時刻サーバーを、信頼性の高い時刻サーバーとなるように設定する。
時刻マスターとなる時刻サーバーは同期先がありません。なので、時刻同期していなくても時刻同期しているフリをする必要があります。(詳しくは「Windows で時刻あわせ (3) w32tm (Server 側)」を参照)
具体的には以下の設定を行います。C> w32tm /config /update /reliable:yes /LocalClockDispersion:0
- KB232488 問題に対応する。
外部と同期していない場合(同期する時刻サーバーがなんらかの原因で通信できない状況であるとき)、Windows タイムデーモン(Windows Time とは別のサービスと思われる)は 1 時間に 1 回システムクロック(= Free-Running System Clock)とハードウェアクロック(=LOCAL CMOS Clock =RTC)を比較します。その結果 60 秒以上の時間差がある場合、強制的にシステムクロックの値をハードウェアクロックの値に上書きします。つまり、時刻が 1 分進んだり戻ったりします。STEP 調整で 1 分前後するので阿鼻叫喚間違いなしです(汗
KB232488 の文書(http://support.microsoft.com/kb/946033)に書かれている仕様なのですが、当該文書は 2020/7 現在、非公開になっているようです。今回時刻マスターにしたい Windows は外部の時刻サーバーと同期していないので、この現象が発生します。
対策は以下の3通りです。- なにもしない
時刻マスターは 1 分の急変が発生しますが、時刻クライアントは slew 調整をすると思われるので急変からは免れることを期待します。
欠点は恐らく時刻クライアント間で時刻が一致しないことです。(時刻マスターの時刻が急変したタイミングでクライアントが一斉に時刻調整を始めるわけではないため。時刻クライアントは時刻マスターの時刻を毎秒単位で確認しているわけではありません。) - 定期的に時刻を再設定する
RTC とシステムクロックの差が 60 秒を超えないタイミングで時刻を再設定します。
コマンドプロンプトの TIME コマンドで時刻を設定する場合、コマンド実行直後に設定時刻を RTC に書き込みます。これをタスクスケジューラーを使用して定期的に行うことで RTC とシステムクロックの差が大きくならないようにします。欠点は恐らく、時刻再設定のタイミングで微小な時刻(システムクロック)の巻戻りがあり、微小ではあるものの同じ時刻を二度繰り返すことと、その微小な誤差が累積されていくことで標準時との誤差が拡大することが予想されることです。
- 「自動的な時刻補正」を無効にする
timeadjx(http://www.monyo.com/technical/products/timeadjx/)のような外部ツールを使用して RTC とシステムクロックの時差チェックを無効にします。
C> timeadjx.exe set 156000
欠点は Windows 標準でないツールを使用しなくてはならなくなることです。また同様の処理は w32tm の内部でも行っている(例えば slew 調整では上記の 156000 の値を微調整することで進めたり遅らせたりをしている)はずなので処理が競合するかもしれません。具体的には「自動的な時刻補正」を無効にしていたつもりが、その後に w32tm などの他のプロセスが後から有効に変えていた、などです。
- なにもしない
こんなことまでして Windows を時刻マスターにすることが良いのか?というと謎なので、そのような要求があれば今一度よく考えてから対処するようにしましょう。
さて、ここで諸悪の元凶(?)となっている KB232488 の動作を確認してみます。
- 上位の時刻サーバーとの同期を切断します。
ピア(上位の時刻サーバー)の登録を削除し、時刻ソースが「Local CMOS Clock」か「Free-running System Clock」であることを確認します。同期先サーバーを設定している場合は、存在しないアドレスに変えるかレジストリのエントリー(\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters\NtpServer)を削除(空文字に)するかします。
C>w32tm /query /status 閏インジケーター: 0 (警告なし) 階層: 1 (主参照 - 電波時計で同期) 精度: -6 (ティックごとに 15.625ms) ルート遅延: 0.0000000s ルート分散: 10.0000000s 参照 ID: 0x4C4F434C (ソース名: "LOCL") 最終正常同期時刻: 2020/07/18 12:53:39 ソース: Local CMOS Clock ポーリング間隔: 10 (1024s)
C>w32tm /query /status 閏インジケーター: 3 (最後の 1 分間は 61 秒) 階層: 0 (未指定) 精度: -6 (ティックごとに 15.625ms) ルート遅延: 0.0000000s ルート分散: 10.0000000s 参照 ID: 0x00000000 (未指定) 最終正常同期時刻: 2020/07/18 12:53:39 ソース: Free-running System Clock ポーリング間隔: 10 (1024s)
ちなみに「Local CMOS Clock」と「Free-running System Clock」の違いは以下のような感じです。
- Local CMOS Clock
PC 起動直後、およびその状態から時刻サーバーと同期がとれなくて 24 時間未満のときの表示。
「Local CMOS Clock」は直感的に CMOS Clock(=RTC)と同期しているかのように見えますが、PC 起動時に RTC を参照した時刻を元にしたというだけで、動作中に RTC と協調,同期しているわけではないです。 - Free-running System Clock
時刻サーバーと同期がとれなくて 24 時間以上経過したときの表示。
Free-running なので「同期する先のない」という意味だとおもってよいと思います。
そういうわけで表現は違いますが、ともに「時刻同期できていない」という点は共通です。
- Local CMOS Clock
- システムクロックと RTC の時刻を 1 分以上ずらします。
ずらすために timeadjx (http://www.monyo.com/technical/products/timeadjx/) というツールを使用します。
ダウンロードすると .\timeadjx-0.2\Release フォルダのに timeadjx.exe があるのでそれを使用します。
まずは、1 秒あたり 10 秒進めるために 1560000 (= 156000ns × 10) を設定します。
C>timeadjx set 1560000 SetSystemTimeAdjustment() 呼び出し中... 割込み発生時の加算時刻: 1560000 (100ns単位) 定期的な時刻調整 : 有効 自動的な時刻補正 : 無効 (自動的な時刻補正の詳細は、KB232488を参照してください)
実行するとものすごい勢い (1 秒で 10 秒分) で時刻が進むと思います。
6 秒以上経過したらデフォルトに戻します。C>>timeadjx set 0 SetSystemTimeAdjustment() 呼び出し中... 割込み発生時の加算時刻: 0 (100ns単位) 定期的な時刻調整 : 無効 自動的な時刻補正 : 有効 (自動的な時刻補正の詳細は、KB232488を参照してください)
- RTC の値を確認します。
RTC(ハードウェアクロック)の値を確認するために RWEverything (http://rweverything.com/ )というツールを使用します。
ダウンロードは RWportable~ というのを選択します。プラットフォームに応じて 32bit/64bit のいずれかをダウンロードします。
解凍すると RW.exe というのがあるのでそれを実行します。
- しばらく放置します。
最大 1 時間くらい放置します。すると時刻が戻っていることに気付くはずです。
イベントビューアをみると、システムログのソース「Kernel-General」、イベント ID=1 が記録されているのが確認できます。システムクロックが RTC に同期したこと、同期前と同期後の時刻が記録されています。
22:19:35 から 22:14:43 に変更になったと書いてありますが UTC での記録ですから、JST だと 07:19:35 から 07:14:43 に変更ということですね。 - ふたたび RTC の値を確認します。
RTC の時刻とシステムクロックの時刻が一致しているのが確認できます。
この例ではシステムクロックと RTC がともに 07:20:14 となっていることが確認できます。Address 00h 01h 02h 03h 04h 05h 06h 07h 08h 09h Function 秒 分 時 日 月 年 Value(BCD) 14 20 07 19 07 20
実行すると、メニューから「Specific」→「IO Index/Data」→「CMOS - 70/71」を選択すると、CMOS のデータを表示します。
そうすると、RTC の時刻とシステムクロックの時刻がずれているのが確認できます。
RTC の方は、04 番地が時、02 番地が分、00 番地が秒になっています。
この例ではシステムクロックが 07:06:17 に対して RTC が 07:01:24 でシステムクロックが 5 分くらい進んでいます。
Address | 00h | 01h | 02h | 03h | 04h | 05h | 06h | 07h | 08h | 09h |
---|---|---|---|---|---|---|---|---|---|---|
Function | 秒 | 分 | 時 | 日 | 月 | 年 | ||||
Value(BCD) | 24 | 01 | 07 | 19 | 07 | 20 |
ooltcloud
次の記事> Windows で時刻あわせ (7) Powershell Tools
http://ooltcloud.sakura.ne.jp/blog/202007/article_25111413.html
Link | 2020年7月25日 11:47