HWCLOCK

Section: System Administration (8)
Updated: July 2017
Index Return to Main Contents
 

名前

hwclock - タイムクロックのユーティリティ  

書式

hwclock [function] [option...]  

説明

hwclock はタイムクロックの管理ツールである。 以下のことが実行できる。 ハードウェア・クロックの値を、ずれの値に基づいて表示する。 ハードウェア・クロックの値を、指定した時刻に設定する。 ハードウェア・クロックの値を、システム・クロックの値に設定する。 システム・クロックの値を、ハードウェア・クロックの値に設定する。 ハードウェア・クロックのずれを補償する。 システム・クロックのタイムスケールを訂正する。 カーネルのタイムゾーン、NTP タイムスケール、紀元年 (Alpha のみ) を設定する。 将来のハードウェア・クロックの値を、ずれの値に基づいて、予想する。

v2.26 から重要な変更が、 --hctosys の機能と --directisa オプションに対して行われ、新しいオプション --update-drift が追加された。 下記のそれぞれの説明を参照すること。  

機能

以下の機能は排他であり、1 度に 1 つしか設定できない。 何も指定されない場合、デフォルトは --show である。
-a, --adjust
最後にハードウェア・クロックを合わせた時点からの経過時間に対して生じる、 時計の規則的なずれを補償するために、 一定の時間をハードウェア・クロックの時刻から増減する。 詳細は以下の 時刻合わせ機能 の議論を参照のこと。
--getepoch
--setepoch この機能は Alpha マシンのみであり、 Linux カーネル RTC ドライバを通じてのみ利用可能である。

この機能では、カーネルのハードウェア・クロックの紀元年の値の 読み込みと設定を行う。 紀元年は西暦の何年が、ハードウェア・クロックの 0 年として参照されるかを示す数値である。 例えば、マシンの BIOS がハードウェア・クロックの年カウンタに 1952 年以降の経過年数を用いている場合には、 カーネルでのハードウェア・クロック紀元年は 1952 でなければならない。

--setepoch の機能は、年を指定するために、 --epoch オプションを使う必要がある。 例:

hwclock --setepoch --epoch=1952

RTC ドライバは現在の紀元年を値を推定しようとするので、設定する必要はない。

この紀元年の値は、 hwclock が Alpha マシンでハードウェア・クロックを読み書きするとき常に用いられる。 ISA マシンでは、カーネルは固定のハードウェア・クロックの紀元年として、 1900 年を用いる。

--predict
--date オプションと /etc/adjtime の情報に基づいて、ハードウェア・クロックが将来読み出す値を予測する。 例えば、ハードウェア・クロックのウェイクアップ (別名、アラーム) を設定する時に、 ずれを考慮するのに役立つ。 rtcwake(8) を参照すること。

ハードウェア・クロックを現在のオペレーティングシステムの hwclock コマンドから変更しない場合、 例えば '11 分モード' またはデュアルブートした他の OS から変更する場合、 この機能を使ってはならない。

-r, --show
--get
ハードウェア・クロックを読んで、時刻を ISO 8601 フォーマットで標準出力に表示する。 ハードウェア・クロックを協定世界時 (UTC) にしていても、 表示はローカル・タイムである。 --localtime オプションを参照すること。

ハードウェア・クロック時刻を表示するのは、 どの機能も指定されてない場合のデフォルトである。

--get 機能は、時刻の読み出しを行う際に、 /etc/adjtime の情報に基づいてずれの補正を適用する。 ハードウェア・クロックを現在のオペレーティングシステムの hwclock コマンドから変更しない場合、 例えば '11 分モード' またはデュアルブートした他の OS から変更する場合、 この機能を使ってはならない。

-s, --hctosys
システム・クロックをハードウェア・クロックに合わせる。 ハードウェア・クロックから読み出した時刻は、 システム・クロックに設定される前に、 規則的なずれ (systematic drift) を考慮して補正される。 下記の 時刻合わせ機能 での議論を参照すること。

システム・クロックは UTC タイムスケールで保持される。 これにより、日付時刻のアプリケーションは、 システムに設定されたタイムゾーンと組み合わされて、正しく動作する。 ハードウェア・クロックがローカル時刻で保持されている場合、 システム・クロックに設定する前に、 読み出した時刻を UTC タイムケールにシフトさせなければならない。 --hctosys の機能は、これを /etc/adjtime ファイル、またはコマンドライン引き数 --localtime--utc の情報に基づいて行う。 注意: 夏時間の補正は行われない。 下記の ローカル時刻 vs UTC の議論を参照すること。

カーネルはタイムゾーンの値を保持し、 --hctosys の機能でシステムに設定されるタイムゾーンに設定する。 システムのタイムゾーンは、TZ 環境変数や /etc/localtime ファイルで設定され、 tzset(3) と同じように解釈される。 カーネルのタイムゾーンの obsolete なフィールドである tz_dsttime は 0 に設定される。 (このフィールドがかつて意味していた内容に関しては settimeofday(2) を参照のこと。)

起動スクリプト内で使用される場合、ブートからの --hctosys 機能の最初の呼び出しを、 settimeofday(2) にする。 これは、 persistent_clock_is_local カーネル変数を使って、NTP の '11 分モード' タイムスケールを設定する。 ハードウェア・クロックのタイムスケール設定が変更された場合、 カーネルに通知するためには再起動が必要である。 下記の カーネルによるハードウェア・クロックの自動同期 の議論を参照すること。

これはファイルシステムを read/write でマウントする前に、 システムの起動スクリプトで使うのによい機能である。

この機能は実行中のシステムに使うべきではない。 システム時刻が飛んでしまうと、ファイルシステムのタイムスタンプが 破損するといった問題を引き起こす。 NTP の '11 分モード' のように、 何かがハードウェア・クロックを変更すると、 --hctosys は、ずれの補償を含めて時刻を正しく設定できない。

ずれの補償は、 /etc/adjtime のずれの要素を 0 に設定することで、中止することができる。 この設定は、シャットダウン時に (またはどこかで) --update-drift オプションが --systohc と一緒に指定されるまで継続する。 もう 1 つのずれの補償をさせない方法は、 --hctosys 機能の呼び出しで、 --noadjfile オプションを使うことである。 3 番目の方法は、 /etc/adjtime ファイルを削除することである。 この場合、 hwclock はデフォルトでハードウェア・クロックで UTC タイムスケールを使う。 ハードウェア・クロックがローカル時刻で刻まれている場合、 このファイルで定義されている必要がある。 ファイルが存在しない場合、 hwclock --localtime --adjust; を呼び出すことでローカル時刻にすることができる。 このコマンドは実際にはハードウェア・クロックを調整せず、 ローカル時刻の設定がされて、ずれ要素が 0 のファイルを生成する。

hwclock のずれ補正を中止する条件は、複数のオペレーティングシステムを デュアルブートする時に、望ましい効果がある。 Linux のインスタンスが停止して、他の OS がハードウェア・クロックの値を変更した場合、 Linux のインスタンスを再度起動したときに、適用されるずれ補正が不正になる。

hwclock のずれ補正が正しく動作するには、Linux インスタンスが動作していないときに、 ハードウェア・クロックが変更されないことが、絶対必要である。

--set
ハードウェア・クロックを --date オプションで指定した時刻に設定し、 /etc/adjtime のタイムスタンプを更新する。 --update-drift オプションを指定すると、ずれの要素を (再) 計算する。 このオプションを指定しないと、 --set は失敗する。 以下の --update-drift を参照すること。
--systz
これは --hctosys 機能の代替である。 これはハードウェア・クロックの読み出しと、 システム・クロックの設定も行わない。 結果として、ずれの補正を行わない。 この機能は、バージョン 2.6 以降のカーネルのシステムの起動スクリプトで使うことを意図している。 このシステムでは、カーネルの起動時に、 システム・クロックがハードウェア・クロックの値に設定される。

上記の --hctosys 機能では、詳細には以下に示すことが行われている:

システム・クロックのタイムスケールを必要に応じて UTC に補正する。 システム・クロックを設定することで、これを行う代わりに、 hwclock はカーネルに単純に通知を行い、変更を行う。
カーネルの NTP '11 分モード' タイムスケールを設定する。
カーネルのタイムゾーンを設定する。

最初の 2 つは、起動後の最初の settimeofday(2) の呼び出しで実行される。 結果として、このオプションは起動スクリプトで使われる場合にのみ 意味を持つ。 ハードウェア・クロックのタイムスケール設定が変更された場合、 カーネルに通知するために再起動が必要である。

-w, --systohc
ハードウェア・クロックをシステム・クロックに設定し、 /etc/adjtime のタイムスタンプを更新する。 --update-drift オプションを指定すると、ずれの要素を (再) 計算する。 このオプションを指定せずに、 --systohc を実行すると失敗する。 下記の --update-drift を参照すること。
-V, --version
バージョン情報を表示して、終了する。
-h, --help
ヘルプを表示して、終了する。
 

オプション

--adjfile=filename
デフォルトの /etc/adjtime ファイルパスを上書きする。
--date=date_string
このオプションは --set または --predict 機能と一緒に使わなければならない。 さもなければ、このオプションは無視される。
hwclock --set --date='16:45'
hwclock --predict --date='2525-08-14 07:11:05'

ハードウェア・クロックを UTC にしたい場合でも、引き数はローカル時刻でなければならない。 --localtime オプションを参照すること。 よって、引き数にはタイムゾーンの情報を含めるべきではない。 また、引き数を "+5 minutes" のように相対時刻にするべきでもない。 なぜなら hwclock の精度は、引き数の値とキーが押された時の関係に依存しているからである。 小数で指定した秒は、黙って落とされる。 このオプションは、多くの時刻と日付のフォーマットを解釈できるが、 前のパラメータに従う。

--delay=seconds
このオプションを使うと、クロック時刻を設定する際に、 内部的に使われる遅延を上書きすることができる。 デフォルトの遅延は、rtc_cmos については 0.5 (500ms) であり、 他の RTC タイプについては 0 である。 RTC タイプが (sysfs から) 決定できない場合、 後方互換性のため、デフォルトを 0.5 にする。

500ms のデフォルトは、一般に用いられている MC146818A 互換 (x86) ハードウェア・クロックに基づいている。 ハードウェア・クロックは任意の整数の時刻プラス 0.5 秒にのみ設定できる。 小数の秒を設定または取得するインタフェースがないので、 整数の時刻にする必要がある。 追加される 0.5 秒の遅延は、新たな時刻が設定されてから正確に 500ms 後に、 ハードウェア・クロックが更新されるからである。 残念なことに、この挙動はハードウェア依存であり、 同様な場合にも別の遅延時間が必要になる。

-D, --debug
--verbose を使うこと。 --debug オプションは古く、将来のリリースで、別の目的に使われるか、 削除される。
--directisa
このオプションは、x86 と x86_64 ファミリーの ISA 互換マシンでのみ意味を持つ。 他のマシンでは、何の効果もない。 このオプションは hwclock に指令して、ハードウェア・クロックへのアクセスに 直接 I/O 命令を用いるようにさせる。 このオプションを指定しないと、 hwclock は rtc デバイスを用いようとする (rtc が RTC デバイスドライバで駆動されていることを仮定する)。 v2.26 以降では、rtc ドライバが利用できない場合、 directisa を自動で使わなくなった。 これを使うと、2 つのプロセスが同時にハードウェア・クロックにアクセスするのを 許可してしまい、安全でない条件が生み出されてしまうからである。 ユーザー空間からの直接ハードウェアアクセスは、 テストして、トラブルシュートして、他の全ての手段が失敗した場合の 最後の手段として使うべきである。 --rtc オプションを参照すること。
--epoch=year
このオプションは --setepoch 機能を使うときに必要である。 year の最小値は 1900 である。 最大値はシステム依存で (ULONG_MAX - 1) である。
-f, --rtc=filename
hwclock のデフォルトの rtc デバイスファイル名を上書きする。 指定しない場合、下記の順で見つかった最初のものを使う:
/dev/rtc0
/dev/rtc
/dev/misc/rtc
IA-64 の場合:
/dev/efirtc
/dev/misc/efirtc
-l, --localtime
-u, --utc ハードウェア・クロックがどちらのタイムスケールを使うかを指定する。

ハードウェア・クロックは、UTC またはローカルのいずれかのタイムスケールを使うように設定できる。 しかし、クロック自身がどちらが使われているかを返すことはない。 --localtime または --utc オプションは、この情報を hwclock コマンドに伝える。 間違ったオプションを指定すると (またはどちらも指定せず、間違ったデフォルトが使われると)、 ハードウェア・クロックの設定も読み出しも不正になる。

--utc--localtime も指定しない場合、最後に set 機能 (--set, --systohc, --adjust) を実行した時に使われたオプションが使われる。 これは /etc/adjtime に記録されている。 adjtime ファイルが存在しない場合、デフォルトは UTC である。

注意: ハードウェア・クロックがローカル時間で保持されている場合、 夏時間への変更は不整合を起こす。 下記の ローカル時刻 vs UTC の議論を参照すること。

--noadjfile
/etc/adjtime によって提供される機能を無効にする。 このオプションを使うと、 hwclock/etc/adjtime の読み込みも書き込みもしない。 このオプションを使うときは、 --utc または --localtime を指定しなければならない。
--test
実際にはシステム、つまりクロックまたは /etc/adjtime に変更は行わない (--verbose は暗黙のうちにこのオプションを指定する)。
--update-drift
/etc/adjtime に書かれたハードウェア・クロックのずれの要素を更新する。 このオプションは --set または --systohc とのみ一緒に利用できる。

設定には、最小限 4 時間の期間を開ける必要がある。 これは計算を不正にしないためである。 期間を長くするほど、ずれの要素の計算結果は正確になる。

このオプションは、v2.26 で追加された。 なぜなら、システムで hwclock --systohc をシャットダウン時に呼び出すことが典型的にあり、 以前の挙動では、ずれの要素を自動的に (再) 計算しており、 問題を引き起こしていた:

NTP を '11 分モード' を使っている場合、 カーネルのずれ要素は 0 に近い値にされる。
「コールド」ずれ補正を使うことを許可しない。 「コールド」ずれ補正を使う多くの設定では、良好な結果を生み出す。 「コールド」とは、ずれ要素に重大な影響がある場合に、 マシンを停止することを意味している。
シャットダウン毎にずれ要素を (再) 計算することは、準最適な結果を生み出す。 例えば、短期間しか使われない条件は、 マシンの異常でホットなずれ要素の計算で、範囲外にしてしまう。
(v2.31 の時点で --update-drift を使わず、RTC が読み込まれない場合) シャットダウンの時間が顕著に長くなる。

hwclock にずれ要素を計算させるのは、良いスタートポイントとなるが、 最適な値に調整するには、 /etc/adjtime ファイルを直接編集する必要がある。 多くの設定では、一度マシンの最適なずれ要素が作られれば、 変更する必要はない。 よって、自動的にずれを (再) 計算する以前の挙動は変更され、 今はこのオプションを使う必要がある。 下記の 時間調整の機能 の議論を参照すること。

このオプションは、ハードウェア・クロックを設定する前に読み込む 必要がある。 読み込めない場合、このオプションは設定機能を失敗させる。 これは、例えば、電源の障害でハードウェア・クロックが壊れている 場合に起こる。 この場合、このオプションなしで最初にクロックを設定しなければ ならない。 これが動作しない場合、ずれの補正要素はどうしても不正になる。

-v, --verbose
hwclock が内部で実行していることをより詳細に表示する。
 

注意

 

Linux システムにおける時計

2 つタイプの日付時刻の時計がある:

ハードウェア・クロック: このクロックは独立したハードウェアデバイスで、 独自の電源系統 (電池、コンデンサーなど) を持っており、 マシンが電源オフされたり、電源プラグが抜かれた場合でも、動作する。

ISA 互換のシステムでは、このクロックは ISA 規格の一部として定義されている。 コントロールプログラムはこの時計に対して 1 秒単位で読み書きできるが、 秒針の変化を検出することもできるので、 実際には仮想的に無限大の精度を持っていることになる。

この時計は一般にハードウェア・クロック、リアルタイム・クロック、RTC、 BIOS クロック、CMOS クロックなどと呼ばれる。 hwclock では「ハードウェア・クロック (原文では Hardware Clock)」を用いる。 Linux カーネルは永続 (persistent) クロックも参照する。

非 ISA システムではいくつかのリアルタイムクロックがあり、 その中の一つが独自の電源系統を持っている。 超低電力の外部 I2C または SPI クロックチップが、 ハードウェア・クロックとしてバックアップバッテリーとともに使われ、 より多くの目的で使われる高機能の統合されたリアルタイムクロックを初期化する。

システム・クロック: この時計は Linux カーネルの一部で、 タイマ割り込みによって駆動されている (ISA システムでは、タイマ割り込みは ISA 標準の一部である)。 すなわち Linux が起動している間しか動作しない。 システム時刻は UTC 1970/01/01 00:00:00 からの経過秒数である (より簡単に言えば UTC 1969 年終了後の経過秒数である)。 しかしシステム時刻は整数ではなく、仮想的に無限大の精度を持っている。

Linux ではシステム・クロックがすべての基準となる時計である。 ハードウェア・クロックの基本的な役割は、システムが動いていない間にも 時計を動かしつづけることである。 そのため、起動時にシステム・クロックを初期化する。 ISA システムの設計対象であった DOS においては、 ハードウェア・クロックがただ一つの実時間時計であることに注意すること。

システム・クロックには不連続が存在してはならない。 これはシステムが走っている間に date(1) プログラムを実行して時計を合わせるような場合でも同様である。 一方ハードウェア・クロックには、システムの実行中にでも何を行ってもよい。 次回 Linux が起動したときに、 ハードウェア・クロックからこの調整された時間が使用される。 注意: hwclock --systohc がシャットダウン時に呼ばれるので、 これは現在のところ大部分のシステムで利用できない。

Linux カーネルのタイムゾーンは、 hwclock で設定される。 しかし注意してほしい -- 「カーネルが自分をどのタイムゾーンにいると思っているか」など、 誰も気にしていないのである。代わりに、タイムゾーンに関わるプログラム (おそらくローカルな時間を表示しようとしているもの) は、 ほぼ間違いなく従来用いられてきた方法でタイムゾーンを決定する。 つまり TZ 環境変数や /etc/localtime ファイルを、 tzset(3) で説明されているようなやり方で参照するのである。 しかしカーネルのタイムゾーンの値を見るプログラムも存在するし、 カーネルの周辺部分 (ファイルシステムなど) もこちらを参照する。 vfat ファイルシステムなどがそうである。カーネルのタイムゾーンの 値が間違っていると、vfat ファイルシステムはファイルのタイムスタンプの 設定・取得を間違ってしまう。 他の例は、カーネルの NTP '11 分モード' である。 カーネルのタイムゾーンの値と persistent_clock_is_local 変数が間違えている場合、ハードウェア・クロックが '11 分モード' で設定が不正になる。 下記の カーネルによるハードウェア・クロックの自動同期 の議論を参照すること。

hwclock--hctosys または --systz の機能で カーネルのタイムゾーンを TZ や /etc/localtime の値に設定する。

カーネルのタイムゾーンの値は実際には 2 つの部分からなる。 1) tz_minuteswest フィールド: (DST でない) ローカルタイムが UTC から何分遅れているかを表す。 2) tz_dsttime: 夏時間 (DST) の形式を表し、 現在地の現在時刻に影響する。 この 2 番目のフィールドは Linux では用いられず、常に 0 となる。 settimeofday(2) も参照のこと。  

ハードウェア・クロックへのアクセス方法

hwclock はハードウェア・クロック時刻の取得や設定に、いろいろな方法を用いる。 もっとも普通のやり方は、rtc デバイススペシャルファイルに対して I/O を行う方法である。 これは rtc デバイスドライバで動作することを前提としている。 Linux システムは、udev と複数のハードウェア・クロックをサポートする rtc フレームワークも使う。
 --rtc
オプションで指定することで、デフォルトの rtc デバイスを上書きできる。

しかし、この方法は古いシステムでは rtc ドライバがないので、利用できない。 これらのシステムでは、ハードウェア・クロックへのアクセス方法は システムのハードウェアに依存している。

ISA 互換システムでは、 hwclock は時計を構成していた「CMOS メモリ」のレジスタに直接アクセスすることができた (ポート 0x70 と 0x71 に I/O を行う)。 これを行うには hwclock の実効ユーザー ID がスーパーユーザーでなければならない。 この方法は、 --directisa オプションを指定することで使用できる。

これはクロックにアクセスするには本当に貧弱な方法で、 ユーザー空間プログラムが一般に直接 I/O がサポートされず、 割り込みが禁止されている理由となっている。 hwclock は、これをテスト、トラブルシュートのために提供しており、 動作している rtc デバイスドライバがない場合に ISA システムでアクセスを行う唯一の方法になる。  

時刻合わせ機能

通常ハードウェア・クロックはそれほど正確なものではない。 しかし、その「不正確さ」は完全に予測できるものである。 すなわち、時計は一日あたり同じ時間だけ進む(あるいは遅れる)のである。 これを規則的なずれ (systematic drift) と呼ぶことにする。 hwclock--adjust の機能は、この規則的なずれに対応する補正量を求め、 ハードウェア・クロックに適用する。

以下に動作原理を述べる。 hwclock/etc/adjtime というファイルを管理し、そこに履歴情報を保管する。 このファイルを adjtime ファイルと呼ぶ。

adjtime ファイルがない状態から話をはじめる。 hwclock --set コマンドを用いてハードウェア・クロックを現在の正しい値に合わせたとする。 このとき hwclock は adjtime ファイルを作成し、そこに現在の時刻を「最後に時計合わせ (calibration) が行われた時刻」として記録する。 5 日後に時計は 10 秒進んだとし、それを修正するために再び hwclock --set --update-drift が実行されたとする。 hwclock は adjtime ファイルを更新し、 現在の時刻を最後に時計合わせが行われた時刻として記録、 同時に 2 秒/日という値を規則的なずれの値として記録する。 24 時間が経過したときに hwclock --adjust コマンドを実行すると、 hwclock は adjtime ファイルを参照し、放っておかれた時計は一日に 2 秒進むこと、 時計はちょうど一日だけ放置されていたことを読みとる。 そこで hwclock はハードウェア・クロックから 2 秒を差し引き、現在の時刻を時計の補正 (adjustment) が行われた時刻として記録する。 さらに 24 時間が経過したときに hwclock --adjust を実行すれば、 hwclock はまた同じことを行う。 つまり 2 秒を差し引き、現在の時刻を adjtime ファイルに書き込む。

--update-drift オプションを --set または --systohc と使うと、規則的なずれの割合が、完全にずれ補正された 現在のハードウェア・クロックの時間を、新しく設定した時間と比較することで、 (再) 計算される。 これにより、adjtime にある最後に補正されたタイムスタンプに基づいて、 24 時間のずれの割合を計算する。 そして、このずれ要素は /etc/adjtime に保存される。

ハードウェア・クロックが設定される時に、少しのエラーが生じる。 そのため、 --adjust は調整を 1 秒以内に収める。 その後、再度調整をする時に、累積したずれが 1 秒以上の場合、 --adjust は小数のずれを含めて調整する。

hwclock --hctosys も、ハードウェア・クロックから読み取って、システム・クロックに設定する前に、 adjtime ファイルデータを使う。 これは、 --adjust の 1 秒の制限を共有せず、1 秒以下のずれの値を補正する。 このオプションは、ハードウェア・クロックも adjtime ファイルも変更しない。 システムがハードウェア・クロックを補正する必要がなければ、 --adjust を使う必要性もなくなる。  

adjtime ファイル

調整のみを行うという歴史的な目的で名前が付けられているが、 hwclock の 1 回の呼び出しから次の呼び出しで使われる 他の情報も格納されている。

adjtime は ASCII ファイルであり、フォーマットは以下の通り:

1 行目は 3 つの数値からなり、それぞれ空白で区切られる: 1) 1 日あたりに生じる規則的な時刻ずれを秒で表したもの (浮動小数点型 10 進): 2) 最後に補正あるいは時計合わせを行った時刻を 1969 UTC からの経過秒数で表したもの (10 進整数): 3) 10 進整数の 0 (clock(8) との互換性のためのもの)

2 行目: 数値が 1 つ: 最後に時計を合わせた時刻を 1969 UTC からの経過秒数で表したもの。 時計合わせが一度もされていなかったり、以前の時計合わせに問題があった (例えばその時計合わせ以降にハードウェア・クロックの 時刻が不正なことがわかったとかの) 場合には 0 が入る。 これは 10 進の整数である。

3 行目: "UTC" または "LOCAL"。ハードウェア・クロックが 協定世界時かローカルタイムかを示す。 この値は hwclock にコマンドラインを指定すればいつでも上書き可能である。

以前 clock(8) で使っていた adjtime ファイルは hwclock でもそのまま使うことができる。  

カーネルによるハードウェア・クロックの自動合わせ

ハードウェア・クロックを正しい値に同期させるのに、 別法が取れるようなシステムもある。 Linux カーネルには、11 分ごとにシステム・クロックを ハードウェア・クロックにコピーするようなモードが存在する。 このモードはコンパイル時オプションであるので、 全てのカーネルがこの機能を持っているわけではない。 これは、何らかの洗練された方法 (NTP など) でシステム・クロックを 同期できている時には、よいモードであろう。 (NTP とは、ネットワークのどこかにあるタイムサーバーか、システムに付属した 電波時計にシステム・クロックを同期させる手法である。RFC 1305 を見よ。)

カーネルが '11 分モード' オプションを付けてコンパイルされていると、 カーネルのクロック discipline が同期状態の場合に、 アクティブになる。 この状態になると、カーネルの time_status 変数のビット 6 (マスク 0x0040 でセットされるビット) がクリアされる。 この値は、 adjtimex --print または ntptime コマンドの 'status' 行として出力される。

これには外部への影響がある。 NTP デーモンはカーネルのクロック discipline を同期状態にするので、 '11 分モード' を有効にする。 '11 分モード' は、 hwclock --hctosys を含めて、システム・クロックを昔のやり方で設定すると、無効になる。 しかし、NTP デーモンがまだ動作していると、 '11 分モード' を有効に戻し、システム・クロックを同期させる。

'11 分モード' を有効にしてシステムが動作している場合、 特にハードウェア・クロックがローカルタイムスケールを使うように 設定されている場合、 --hctosys または --systz を起動スクリプトで使う必要がある。 ハードウェア・クロック使われているタイムスケールをカーネルに 通知しない限り、間違えたものを使う可能性がある。 カーネルは UTC をデフォルトとして使う。

システム・クロックを設定するユーザー空間コマンドが、 ハードウェア・クロックが使うタイムスケールが何かをカーネルに通知する。 これは persistent_clock_is_local カーネル変数で通知される。 --hctosys または --systz が最初の場合、adjtime ファイル、または適切なコマンドライン引き数に基づいて この変数を設定する。 この機能を使って、ハードウェア・クロックのタイムスケール設定を 変更した場合、カーネルに通知するためには、再起動が必要である。

hwclock --adjust は NTP '11 分モード' と一緒に使うべきではない。  

ISA ハードウェア・クロックの「世紀値 (Century value)」

その手の標準の中には、ISA マシンの CMOS 50 バイト目を、 現在の世紀の指標として定義しているものがある。 hwclock は、このバイトの読み書きを行わない。 なぜならこのバイトをそのようには利用していないマシンが存在するし、 いずれにしてもこれは実際には必要ないからである。 年の世紀の部分を使えば、現在の世紀を特定するには充分である。

もしこの CMOS の世紀バイトの利用ルーチンを開発した (したい) 方がいたら、 hwclock のメンテナに連絡してほしい。 オプションを付加することは望ましいことであるから。

このセクションが意味を持つのは、ハードウェア・クロックに "direct ISA" によってアクセスしている場合だけであることに注意。 ACPI がハードウェアでサポートされている場合、 世紀値にアクセスする標準的な方法を提供する。  

日付時刻の設定

 

外部同期なしの時刻の維持

この議論は以下の条件に基づいている:

NTP デーモンや cron ジョブのように、日付時刻のクロックを変更するものが動作していない。
システムのタイムゾーンが正しいローカル時刻に設定されていること。 以下の POSIX vs 「正しい」データベース を参照すること。
起動時に以下の順番で呼ばれていること:
adjtimex --tick value --frequency value
hwclock --hctosys
シャットダウンで以下が呼ばれていること:
hwclock --systohc

* adjtimex がないシステムで ntptime を使うことができる。

NTP デーモンで正確な時間が維持されているか否かに関わらず、 システムが適切な日付時刻を維持できるように設定されていることには意味がある。

最初のステップは、概要を明確に理解することである。 2 つの完全に分離されたハードウェアデバイスがそれぞれの速さで動いており、 「正しい」時刻からそれぞれの割合でずれていく。 ずれの補正の方法とソフトウェアは、それぞれで異なる。 しかし、多くのシステムでは、2 つの時計が 起動時とシャットダウン時にそれぞれの値を交換するように設定されている。 今、各デバイスのエラーを含む時刻が相互にやりとりされている。 一方のデバイスについてのみ、ずれの補正が行われるように設定された場合、 他方のずれは一方の補正値で上書きされる。

この問題は、システム・クロックのずれ補正を設定するときに、 マシンをシャットダウンしないことで回避できる。 これにプラスして、(ずれ要素の計算を含む) hwclock の精度は、システム・クロックのずれの割合が修正されているかに依存する。 つまり、システム・クロックの設定は最初にすべきである。

システム・クロックのずれは、 adjtimex(8) コマンドの --tick--frequency オプションで修正できる。 この 2 つのオプションは同時に動作させることができる: tick は大まかな補正をし、frequency は細かな補正を行う。 (adjtimex パッケージがないシステムでは、 ntptime -f ppm を代わりに使うことができる。)

Linux ディストリビューションの中には、システム・クロックのずれを adjtimex の比較操作で自動的に計算するものもある。 1 つのずれた時計を、もう1 つのずれた時計を参照して補正しようとした場合、 犬が自分の尻尾を噛もうとするようなものである。 最終的には成功するかもしれないが、多大な努力と不満が先立ってしまう。 この自動化は、改良して設定なしできるが、 期待される最適な結果はエラーになってしまう。 マニュアル設定のより良い選択肢は、 adjtimex--log オプションである。

より効率的な方法は、 sntp または date -Ins によって単純にシステム・クロックのずれと正確な時間を追いかけ、 補正値を手動で計算する事である。

tick と frequency の値を設定した後、システム・クロックが適切な時間を維持できるまで、 テストと調整を続ける。 より詳細な情報と、手動でのずれの計算のデモンストレーションの例については、 adjtimex(8) を参照すること。

システム・クロックがなめらかに刻むようになったら、 ハードウェア・クロックに移る。

原則として、コールドなずれは、多くのユースケースで一番である。 通常のダウンタイムが再起動でのみ構成される 24/7 稼働するマシンでも、 これは真実である。 この場合、ずれ要素の値は少し異なる。 しかし、マシンのシャットダウンが伸びるまれなケースでは、 コールドなずれはより良い結果を生み出す。

コールドなずれの計算ステップ:

1
NTP デーモンが起動時に開始されていないことを確認する。
2
システム・クロックがシャットダウン時に正しくなっている必要がある!
3
システムをシャットダウンする。
4
ハードウェア・クロックを変更せず、拡張した期間 (extended period) をパスする。
5
システムを起動する。
6
すぐに hwclock を使って正確な時間を --update-drift を追加して設定する。

注意: ステップ 6 で --systohc を使う場合、その前にシステム・クロックを 正しく設定しなければならない (ステップ 6a)。

hwclock にずれ要素を計算させるのは、良いスタートポイントとなるが、 最適な値に調整するには、 /etc/adjtime ファイルを直接編集する必要がある。 ハードウェア・クロックが起動時に完全正しくなるまで、ずれ要素を テストして洗練させ続ける。 これをチェックするには、シャットダウンの前にシステム時刻が 正しくなっていることを確認し、次に起動直後に sntp または date -Ins と正確な時間を使う。  

ローカル時刻 vs UTC

ハードウェア・クロックをローカルタイムスケールで保持すると、 夏時間の結果に不整合を起こす。
Linux が夏時間で動作していると、 ハードウェア・クロックにかかれた時刻は夏時間に調整される。
Linux が夏時間で動作していないと、 ハードウェア・クロックにかかれた時刻は夏時間に調整されない。

ISA 互換のシステムでは、ハードウェア・クロックは日付と時間しか保持せず、 タイムゾーンも夏時間という考え方もない。 よって、 hwclock がローカル時刻であると言えば、それが「正しい」ローカル時間であると仮定し、 それから読み出す際に、何の調整も行わない。

Linux は、ハードウェア・クロックが UTC タイムスケールで保持されている場合にのみ、 透過的に夏時間への変更を行う。 システム管理者は簡単に hwclock を使ってローカル時刻を出力し、 --date オプションの引き数に指定することができる。

Linux のような POSIX システムでは、 システム・クロックを UTC タイムスケールで扱うように設計されている。 ハードウェア・クロックの目的は、システム・クロックを初期化することなので、 時刻を UTC で保持することには意味がある。

一方で、Linux はハードウェア・クロックをローカルタイムスケールで提供しようとする。 これは、主に古いバージョンの MS Windows とのデュアルブートのためである。 WIndows 7 からは、正しく動作するように、 RealTimeIsUniversal レジストリキーがサポートされているので、 ハードウェア・クロックを UTC で保持することができる。  

POSIX vs 「正しい」データベース

日付時刻の設定の議論は、タイムゾーンについて言及しないと不完全である。 タイムゾーンの言及は、 tzset(3) で大部分が充分にカバーされている。 ドキュメント化されていない 1 つの領域は、tz または zoneinfo とも呼ばれる、 タイムゾーンデータベースの「正しい」ディレクトリである。

zoneinfo システムには、posix データベースと「正しい」データベースの 2 つがある。 「正しい」データベース (ここでは閏秒付き zoneinfo と呼ぶデータベース) には、 閏秒が含まれるが、posix には含まれない。 「正しい」データベースを使うには、 システム・クロックを (UTC + 閏秒) に設定しなければならない。 これは、(TAI - 10) と同じである。 これにより、閏秒紀元年を考慮した 2 つの日付の間の、正確な秒数を計算できる。 システム・クロックは、閏秒を引いた「正しい」ゾーンファイルを使って、 UTC を含む正しい歴時間をカバーできるようになる。 注意: この設定は実験的と考えられており、問題があることも知られている。

システムが特定のデータベースを使うように設定するためには、 そのディレクトリにある全てのファイルが、 /usr/share/zoneinfo をルートにしてにコピーされていなければならない。 ファイルは、例えば TZ='right/Europe/Dublin' のようにして、posix または「正しい」データベースの サブディレクトリから直接使われることはない。 この方法はとても一般的になっており、上位の zoneinfo プロジェクトが、 posix または「正しい」データベースのサブディレクトリを zoneinfo ディレクトリの外に出して、兄弟のディレクトリに入れることで、 システムのファイルツリーを再構成することができる。

/usr/share/zoneinfo
/usr/share/zoneinfo-posix
/usr/share/zoneinfo-leaps

不幸なことに、Linux ディストリビューションの中には、 パッケージ内で昔のツリー構造に戻しているものもある。 その場合、システム管理者が 'right' サブディレクトリに到達できる問題が残っている。 これは、システムのタイムゾーンが閏秒を含んでいるといるが、 zoneinfo データベースには閏秒が含んでいないという問題を引き起こす。 世界時計のようなアプリケーションが South_Pole タイムゾーンファイルを必要とした場合や、 MTA に email を送る場合や、 hwclock が UTC タイムゾーンファイルを必要とした場合、期待されているように、 ファイルを /usr/share/zoneinfo のルートから取得する必要がある。 これらのファイルには閏秒が含まれていないが、 システム・クロックは今日では閏秒を含んでいるので、 時刻の変換が不正になる。

これらの別々のデータベースを混ぜてファイルをマッチさせるのは、 それぞれがシステム・クロックで別々のタイムスケールを要求するので、 うまくいかない。 zoneinfo データベースは、上記で説明した posix または「正しい」データベースのいずれかを使うか、 データベースのパスを TZDIR 環境変数で指定しなければならない。  

返り値

以下の返り値の 1 つが返される:
EXIT_SUCCESS (POSIX システムでは '0') プログラムの実行に成功した。
EXIT_FAILURE (POSIX システムでは '1') 操作に失敗した。または、コマンド書式が不正である。
 

環境変数

TZ
この変数が設定されると、システムのタイムゾーン設定より優先される。
TZDIR
この変数が設定されると、システムのタイムゾーンデータベースの ディレクトリパスより優先される。
 

ファイル

/etc/adjtime
hwclock の設定と状態ファイル。
/etc/localtime
システムのタイムゾーンファイル。
/usr/share/zoneinfo/
システムのタイムゾーンデータベースのディレクトリ。

hwclock がハードウェア・クロックのアクセスに使うデバイスファイル:
/dev/rtc0
/dev/rtc
/dev/misc/rtc
/dev/efirtc
/dev/misc/efirtc  

関連項目

date(1), adjtimex(8), gettimeofday(2), settimeofday(2), crontab(1), tzset(3)

 

著者

hwclock は 1996 年 9 月に Bryan Henderson (bryanh@giraffe-data.com) が clock(8) をもとに書いた。 clock(8) は Charles Hendrick, Rob Hooft, Haraid Koenig によって書かれた。 完全な履歴と謝辞はソースに書かれている。  

入手方法

hwclock コマンドは util-linux パッケージの一部であり、 https://www.kernel.org/pub/linux/utils/util-linux/ から入手できる。


 

Index

名前
書式
説明
機能
オプション
注意
Linux システムにおける時計
ハードウェア・クロックへのアクセス方法
時刻合わせ機能
adjtime ファイル
カーネルによるハードウェア・クロックの自動合わせ
ISA ハードウェア・クロックの「世紀値 (Century value)」
日付時刻の設定
外部同期なしの時刻の維持
ローカル時刻 vs UTC
POSIX vs 「正しい」データベース
返り値
環境変数
ファイル
関連項目
著者
入手方法

This document was created by man2html, using the manual pages.
Time: 02:55:24 GMT, May 03, 2020