2010年05月28日

uptimeのデバッグ/497日問題

巷にはこういった問題があるらしい。
【497日問題】
http://www.wdic.org/w/TECH/497%E6%97%A5

ざっくり言ってしまうと、
・OSが時間を10ミリ秒単位で管理している。
・OSの持っているmonotonicなタイマーがunsigned int(u32)あたりで定義してある。
といったような条件がそろっている場合に、起動してから連続稼動を続け、ちょうど497日程度経過したころに、タイマーの桁あふれが発生し、動作が不安定になる。
といった現象らしい。


じゃ、Linuxだったらどうなのか?
Linux上のmonotonicなタイマーといえば、uptime(/proc/uptime)。
同じように497日経過したころに、uptimeがオーバーフローしてしまい、挙動がおかしくなってしまうことがあるのかどうかを、確認してみた。


1.まず、カーネル起動時に初期値として持つuptimeの値をいじってしまい、起動直後から497日程度経過した時間とカーネルに勘違いさせてみる。
2.6.31.8でこの実験を実行するために、カーネルソースに下記の変更を加えてみた。

Index: kernel/time/timekeeping.c
===================================================================
--- kernel/time/timekeeping.c (revision 20731)
+++ kernel/time/timekeeping.c (working copy)
@@ -312,6 +312,7 @@
xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
+ xtime.tv_sec = 0x28de800;
update_xtime_cache(0);
total_sleep_time = 0;
write_sequnlock_irqrestore(&xtime_lock, flags);


2.1の変更を加えたカーネルをビルド。
 起動してみると、次のような状態になる。


root@hogehoge:~# cat /proc/uptime
42860653.72 6242.41
root@hogehoge:~# uptime
17:41:31 up 496 days, 1:44, load average: 0.00, 0.00, 0.00
root@hogehoge:~#

うん、496日経過してるねwww

3.んでまぁ、2の状態で1日程放置してみる。
 →これは今はじめたばかりなので、とりあえず、土日と放置してみます。
 まぁ、最初の初期値として、もっとキワドイところを狙っていけばいいという話もあるのですが。。。




といった感じでとりあえず放置しておく予定だけれども、Linux環境ではとりあえず問題なさそうな感じ。

というのも、上記の変更でもわかるかもだけど、Linuxの中ではmonotonicなクロックをtimespec型で管理している。
このtimespec型というのは、./include/linux/time.hにあるように、

struct timespec {
__kernel_time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};

といった型。
ここで、__kernel_time_tがどういった形で定義されているかどうかはわからないけど、とにかくsecondsと、nanosecondsといった形で定義されていることがわかる。

つまり、__kernel_time_tがunsigned long(u32)とかだったとしても、
0xffffffff→268435455→約3106日→約8年
だし、もし仮にunsigned long long(u64)だったりしたら、
0xffffffffffffffff→18446744073709551615→約213503982334601日→584942417355年
と、計算間違ってんじゃねーの?と思うほど途方もない年月がカウント可能であることになる。


といったことで、497日問題はLinuxは無関係そうだとわかったのでした。
ただし、uptimeを参照して、atolといったような処理を経由して使用しているような場合は、個別のアプリレベルで同様な問題が発生する可能性があるので、要注意かな。

uptimeの初期化部分とその構造のお勉強でした。
posted by ゆきち at 19:49| 東京 ☁| Comment(3) | TrackBack(0) | Linux | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。