MIRACLE
メールサービス申込 ユーザー登録 パートナー情報
お問い合わせ FAQ サイトマップ
MIRACLE LINUXの特長 製品紹介 サービス案内 購入 サポート 技術フォーラム

« initrdのその中へ | メイン | カーネルアップデート危機一発 »

2006年6月23日 (金)

時間は無限?

マシンを立ち上げるとLinuxカーネルが立ち上がります。そして、マシンを停止するまでカーネルが動きつづけるわけです。この間、カーネルは刻々と時を刻んでいきます。
そこでカーネルでの時間の管理に使われるのが、jiffiesという変数です。
kernel-2.4では、kernel/timer.cで次のように定義されています。
----
unsigned long volatile jiffies __cacheline_aligned;
----

unsigned longなので、32bit環境では、0〜0xffffffffの範囲を表すことができます。
このjiffiesは、timer割り込みと呼ばれる処理の際に1ずつ増加していきます。timer割り込みの頻度は、"HZ"として定数で定義されています。
linux-2.4.21/include/asm-i386/param.h
----
#ifndef HZ
#define HZ 100
#endif
----
ということで、kernel-2.4のIA32環境では、1秒間に100回のタイマー割り込みが発生し、jiffiesが1秒間に100増えていくということになります。

それでは、jiffiesの値は無限に増やせるのでしょうか?
さきほど示したように、32bit環境では、jiffiesの最大値は0xffffffffなので、その時間までしかカウントできないことになります。計算してみると、約497日(1年5ヶ月)で最大値を迎えることになります。これが噂のjiffiesのオーバーフローです。jiffiesがオーバーフローすると、また0に戻ってカウントしていきます。

さて、jiffiesがオーバーフローすると何か困ることがあるでしょうか?
例えば、今の時間がjiffies変数に入っていて、n秒後にタイムアウトを判断するために、次のようなコードを書いたとします。
----

timeout = jiffies + n;

タイマーセット(timeout);

----

数秒後に、タイムアウト時間が過ぎているかどうか調べてみます。

----

if (jiffies < timeout){

   printk("まだタイムアウトしてないよ!\n");

}

----

こんなコードを書いた時、「噂のjiffiesのオーバーフロー」が発生するとどうなるでしょう? timeoutが32bitの最大値ぎりぎり(例えば 0xfffffff9)に設定されたりしていると、オーバーフロー直後にチェックすると、

-----

if ( 3 < 0xffffffff9 )

  → 真なので、「まだタイムアウトしてないよ!」出力。

-----

といったことになって、正しく処理できなくなってしまいます。

そこで、カーネルではそんな悲しい出来事が起きないように、ちょっとした工夫をしています。

それはここです。
linux-2.4.21/include/sched.h

-----

#define time_after(a,b)         \
        (typecheck(unsigned long, a) && \
         typecheck(unsigned long, b) && \
         ((long)(b) - (long)(a) < 0))
----

jiffiesのようなタイムアウトの判断に使うためのマクロが用意されています。ポイントはここですね。
----
((long)(b) - (long)(a) < 0))
----

こういう計算にすると、jiffiesがオーバーフローしても大丈夫ですね。ポイントは「キャスト」です。(キャストといっても装甲が飛んで軽くなるあれ系とは関係ありません。)

kernel 2.4の多くのコードがこのマクロを使うように書き換えられていますが、まだまだ完璧ではないようです。ちなみにkernel 2.6ではjiffiesが64bit化されているので、オーバーフローまで何日かかることやら...。

トラックバック

このページのトラックバックURL:
http://www.typepad.jp/t/trackback/4447/1141613

このページへのトラックバック一覧 時間は無限?:

» sched_clock()の差分? time_afterでいいじゃん トラックバック 革命の日々!
いつもお世話になっている上川さんのLinux Kernel Watchより http://www.atmarkit.co.jp/flinux/rensai/watch2006/watch06b.html □sched_clock()による時間計測に注意  短期間の処理に要した時間を計りたいとい... [続きを読む]

コメント

コメントを投稿

コメントは記事の投稿者が承認するまで表示されません。

会社情報 採用情報 個人情報保護方針 商標等取り扱い事項 English
Copyright(c)2000-2006 MIRACLE LINUX CORPORATION. All Rights Reserved.