不正確な時計Mini-HOWTO ====================== 原著 By rbean@execpc.com last revised Dec. 1996 日本語訳 吉川雅英 kikkawa@m.u-tokyo.ac.jp last revised Jan. 1997 PCのマザーボード上に使われている時計のチップは、不正確であることは良く知られ ています。Linuxにはこのためのソフトウエアがあって、例え外部の時計が無くても 時計を可能性として*とても*正確にすることができます。しかし、ほとんどの人は、 以下に述べるようないくつかの理由でこのことを知らないようです。 1: 一般的な「how to set up linux」文書の多くには述べられていない。また、インストールのときに自動的にセ ットアップするのは難しそうである。(モデムがあれば理論的には不可能ではないが 。) 2. もし、'man clock'をチェックしたら、clock(3)、つまり、欲しくも無いものが出てくる。('man 8 clock'を試してみよ) 3. 多くの人は、いずれにしろ何時かなどということを気にしないようだ。 4. 時間を気にする数少ない人はlouie.udel.eduからとってきたxntpdパッケージを使っ て、外部の時計、例えばネットワークタイムサーバーやラジオクロックとシンクロを 取ろうとする。 このmini-HOWTOはローテクな方法について書かれている。もし4.にあるような方法に ついて関心があるなら、http://www.eecis.udel.edu/~ntp/を覗いてみることを強く おすすめする。そこなら、あらゆる種類のおもしろそうなものが転がっているし、xn tpdに関する完ぺきな情報も含んでいるし、NISTやUSNOへのリンクもある。(xntpdに 関しては私もこの文書の最後にいくらか述べている。) NOTE:あなたのマシンで2つ以上のOSを動かしている場合には、そのうちの一つだけ でCMOS clockを合わせないと、お互いのOSが干渉してしまいます。LinuxとWindowsを同じマ シンの上で両方とも頻繁に使う場合には、Windows用のシェアウエアの時計プログラ ムのどれかを使ってみると良いでしょう。(上記のURLをたどってみてください。) ========================= 必要なことは全てclock(8) man pageに書かれていますが、このmini-HOWTOでは、これを使う方法を示します。 NOTE: t権限で動かす必要があります。 インストールしてあるかどうかのチェック ====================================== システム起動ファイルの中に、'clock -a'とか'clock -ua'とかが無いか見てみてください。どのディストリビューションを使っているかに よって違いますが、起動ファイルは/etc/rc.localか、/etc/rc.d/rc.sysinit、ある いはそんな感じの場所にあります。 もし、そこで'clock -s'とか'clock -us'が使われていたら、's'を'a'に変えて、/etc/adjtimeがあるかどうかを確認して ください。/etc/adjtimeには、以下のような一行が書かれています。 0.000000 842214901 0.000000 この数字は、補正値(秒/日)、最後に時計が合わされた時刻(1970年1月1日からの 秒数で表される。)、前回時計を合わせたときに切り捨てられた秒数を表しています 。もしこのファイルが無ければ、rootとしてログインして、次のような一行(全部ゼ ロ)で、そのファイルを作成してください。 0.0 0 0.0 そして、'clock -a'か'clock -ua'をシェルからマニュアルで実行して、2番目の数字を更新してください。(ロー カル時間でなく、世界標準時に合わせる場合には'u'を使う。) 時計の狂い率を測定する。 ======================== まず、現在何時かを知る必要があります :-). 日にちも正確では無いかも知れません。私のお気に入りは、WWVの音声アナウンスを( 303)499-7111で聞くことです。(これは料金を取られます。訳注:日本なら117。もち ろんこれも有料)もし、network time serverにアクセスすることができるのであれば、xntpdパッケージの中の'ntpdate'プ ログラムを使うことができます。(カーネルが、CMOS時計との間で混乱しないように -bフラグを使いましょう。)そうでなければ、'date -s hh:mm:ss'で、カーネルの時計を手動でセットして、つぎに、'clock -w'で、カーネルの時計からCMOS時計を合わせます。時計を合わせ終わったら、合わ せた日付をどこか無くならないようなところにメモしておくのを忘れないですださい 。もし、ntpdateを使った場合には、'date +%s'を実行して、1970年1月1日からの秒数をメモしておきましょう。 そして、何日かあるいは何週間かしてから、時計がどれだけ狂っているかを見ること になります。時計を手で合わせる場合には、少なくとも2週間は待っって、せいぜい 0.1秒/日位の正確さで時計の狂い方のみを計算した方がよいでしょう。何カ月かあと なら0.01秒/日くらいの正確さで時計の狂い方がわかります。(もっと正確だという 人も居るかも知れませんが、私はここでは保守的に言うことにします。)もし、'ntp date'を使った場合には、それほど長く待つ必要はありませんが、いずれにしろ、後 でもっと正確に調整することができます。 cronで'clock -a'を走らせることによって、一定間隔でシステムの時計を(較正ずみの)CMOS時計 と歩調を合わせることができます。このコマンドはブートする度にスタートアップフ ァイルからも実行することができま。もし、たびたびブートするのであれば、多分、 あなたの目的には十分です。 ある種のプログラムは、システム時計が一度に1秒以上進んだり、遅れたりするとう まく働かないことがあります。このような問題がある場合には、xntpdかntpdateを使 って、もっと徐々に時計を合わせることができます。 実例 ==== 時計を合わせる -------------- ルートでログインする。 (303)499-7111(音声)をダイヤルする。アナウンスを聞く date -s hh:mm:ss をタイプする。 しかし、時報が聞こえるまでenterを押してはいけません。 ['date'の代わりに'ntpdate'を使えば、電話をかけなくて済みます。] これでカーネルの時計を合わせました。 つぎに clock -w とタイプしてください。これでCMOS時計をカーネル時計に合わせます。 date +%j とタイプして [あるいは、 先ほど'date'の代わりに'ntpdate'を使った場合には'date +%s] 出てきた結果の数字を次の時のためにメモしておいてください。 再度、時計を合わせ、狂いの率を調べる。 -------------------------------------- 前回書いた日付を確認し、 rootでログインし clock -a とタイプする。これにより、カーネルの時計は、現在のCMOS時間と合うようにセット される。 (303)499-7111 (音声)をダイヤルし、アナウンスを聞く。 date をタイプして、待っている間に、時刻をタイプして、時報がなるのを聞いたときに、 enterを押す。でもまだ電話を切らないで。これで、時報の鳴ったときに、コンピュ ータの時計は何時だったのかがわかります。では、 date hh:mm:00 と、タイプしてください。時間の所は、アナウンスよりちょうど1分後のもので、次 の時報を聞いたときに、enterを押してください。(もう電話を切っても構いません 。)hhの所には地域標準時を使ってください。これで'カーネル時計'を合わせました 。次に clock -w とタイプして、新しい(正しい)時刻にCMOS時計を合わせます。 つぎに: date +%j [あるいは 前と同じように'date +%s'とタイプしてください。] これで3つの数字(2つは日付、一つは時刻)が得られたわけです。これによって、 補正率が計算できます。 補正率の計算: ------------- 時報を聞いたときに出てきた'date'は、進んでいましたか?遅れていましたか?も し進んでいた場合には、何秒か引き算しなければならないので、負の数をメモしてく ださい。もし、遅れている場合には、足し算をしなければならないので、正の数をメ モしてください。 次に、2つの日付の差を求めてください。'date +%j'を使用した場合には、数字は一年のうちで何日目かを示しています。(ですから 、1から365の数字になります。うるう年の場合には1から366)もし、前回時計を合わ せてから、1月1日を越したら、365(または366)を2番目の数字に足してください。 もし、'date +%s'を使用した場合には、数字は秒数で表されているので、86400で割って日数を出 してください。 もし、既に補正率が/etc/adjtimeに書かれている場合には、どれだけ既に補正がな されているかを計算する必要があります。もし、補正されすぎている場合には、先ほ ど計算した数字は、その補正率とは逆の符号になっているはずです。補正が足りない 場合には、同じ符号になっているはずです。古い補正率に日数を掛けて、先ほど求め た数字を足して、新しい値を求めてください。(符号も含めて。つまり、2つの数字 が同じ符号なら、大きな数字になりますし、違う符号なら小さな数字になります。) 最後に、その値(秒)を、日数で割ると、新しい補正率が求まるので、古い補正率 の代わりに/etc/adjtimeに書き出してください。今日の日付(秒か、日)も次回の為 にメモしておきましょう。 私の/etc/adjtimeはこんな風になっています: -9.600000 845082716 -0.250655 [9.6秒/日ということは、一カ月で、5分にもなることに注意!] xntpdについてすこし: ==================== システムには2つの時計があります。バッテリー駆動される「リアルタイム時計」で 、システムの電源が落とされている間も時間を刻み続けるもの。(CMOS時計、ハード ウエア時計、あるいはRTCとして知られています。)それから、カーネル時計。(ソ フトウエア時計とか、システム時計とも呼ばれます。)これは、ブート時にCMOS時計 を基準に時間を測り始め、タイマー割り込みに基づいていています。この2つはそれ ぞれ異なった狂い方をしており、お互いに少しずつ狂っていきますし、もちろん「本 当の」時間からも狂っていきます。 xntpdの文書において「時計」は常に「カーネル時計」のことを指しています。xntpd や、timed(あるいは、'adjtimex'システムコールを使うプログラムならどれでも) を走らせた場合には、linuxカーネルは、CMOS時計よりもカーネル時計の方が正確だ と仮定します。そして、CMOS時計をそれ以後11分毎にカーネル時計に合わせ続けます 。(次回ブートするまで)つまり、'clock'は前回いつCMOS時計が合わせられたかは わからないのです。ですから、/etc/adjtimeを使えません。'ntpdate'を使い、起動 ファイルの中であらかじめ時間を合わせておけば、'xnpd'を使うことができます。し かし、起動時にいつも正確な時計にアクセスすることができない場合には、この方法 は役に立ちません。xnpdはこのような場合を考えて設計されていないのです。 Xntpdは、多くの無線時計に対してのドライバーを用意しており、一定の間隔でNIST のダイヤルアップ時刻サービスを呼び出すように設定できます。(呼び出しの間隔が 、電話の請求書に対して及ぼす影響を良く考えるように!)もし、一定以上他の時計 と比べることができない場合には、カーネル時計に対して補正を行います。 ほとんどの無線時計は$3,000-$4000しますが、ちょっとした機器(実際には300ボー のモデム)であなたのコンピュータと、カナダのCHU時刻局(ftp://ftp.udel.edu/pu b/ntp/gadget.tar.Zを見よ。)の周波数に合わせた短波ラジオをつないでも使えます 。Heathkit WWV受信機(「もっとも正確な時計」)も$4-500で、使うことができます。(キット としてではありませんが。)GPS信号には時刻の情報が入っていて、いくつかのGPS受 信機はシリアルポートにつなぐことができます。将来的にはこれも安く手に入れられ るようになるでしょう。 理論的には、誰かがNISTのダイヤルアップ時刻サービスを使って、CMOS時計とカーネ ル時計の両方の狂い率を計算するプログラムを書くことができるはずです。私自身は 、単独でこのようなことを行うプログラムは知りませんが、きっとほとんどのコード はxntpdから得ることができるに違いありません。