LoginSignup
5
4

More than 5 years have passed since last update.

Linuxの時間変数(jiffies)でハマったこと

Last updated at Posted at 2019-03-02

Linuxには色々な時間変数がありますが、このjiffiesにハメられたので記録しておきます。(勝手にハマっただけ)

変数jiffies

Kernel起動時からtick(タイマー割込み)を数えた回数。
#define HZのCONFIG_HZの値で計算される。
仕事の環境では、HZ=200だった。

jiffiesはHZの間隔でカウントアップされていく値である。
つまり、jiffiesの値をHZで割れば、secが算出されるハズ。

32bit環境

jiffies = 348,264 \\
HZ = 200\\
とした場合、\\
\begin{align}
jiffies\ / HZ &= 348,264\ /\ 200 \\
&= 1,741.3\ [sec] \\
&= 29.8\ [min]
\end{align}

この計算は、公式APIのunsigned int jiffies_to_msecs(const unsinged long j)でも同じ計算をしている。
計算式自体は決して間違っていない。

しかし、64bit環境では思ったように答えが出ないのである。

64bit環境

jiffies = 4,295,130,087 \\
HZ = 200\\
とした場合、\\
\begin{align}
jiffies\ / HZ &= 4,795,130,087\ /\ 200 \\
&= 2,395,650.435\ [sec] \\
&= 39,927.50725\ [min]
\end{align}

は?20分ぐらいしか待ってないのに何それ?

jiffiesの初期値

このjiffies、初期値がクッソ特徴的である。

  • 32bit環境 初期値-5分
  • 64bit環境 32bitの初期値に、上位32bitを0埋め
-5分が初期値って?
\begin{align}
jiffies &= -5\ _{(10)}\ [min] \\
&= -6,000\ _{(10)}\ [sec] \\
&= FFFF\ E890\ _{(16)} \\
\end{align}\\
ただし、64bit環境では上位32bitを0埋めするため、\\
0000\ 0000\ FFFF\ E890\ _{(16)}
  • 32bit環境の場合 FFFF E890
    32bitの領域はこれでお終い。0000 0000は32bit領域外。
  • 64bit環境の場合 0000 0000 FFFF E890
    64bit幅なので、上位32bit(0000 0000)は0だが領域として存在している。

jiffiesは符号なし

こいつ、負数を初期値に取るクセしてunsigned型なのだ。
つまり、さっきの-5分はどんどんタイマーカウントを進めていって、5分後に綺麗に0000 0000 0000 0000(16)になる。

メモリ幅による値の変化

5分後、jiffiesの値が綺麗に0になるのはいい。
だが、コンピューターにおける加算して0になるには注意が必要だ。

32bit幅の場合

結局、(0000 0000) FFFF E890の羅列はtick毎に加算されて行って0になる。
その瞬間は(0000 0001) 0000 0000となる。
だが、上位32bit(0000 0001の部分)は32bit領域外なので消えてしまう。
みんな大好きオーバーフローだ。

その結果、32bitでは0000 0000だけが残り、真に0となってしまう。

64bit幅の場合

0000 0000 FFFF E890は加算され続けることで0になろうとするが、そうは問屋が卸さない。
0000 0001 0000 0000となり、32bit幅では消えてしまった上位32bitの1が残り続ける。
つまり、
0000 0001 0000 0000 (16) = 4294967296 (10)
0とはならないのである。

64bit環境では、この値を引いてやらないと正しく計算できないわけだ。

再度、計算し直してみる。

jiffies = 4295130087\\
4294967296 < jiffiesを満たすため、補正処理を導入する。\\
jiffies - 4294967296 = 162791\\
\begin{align}\\
jiffies / HZ &= 162791 / 200\\
&=813.955\ [sec]\\
&=13.6\ [min]\\
\end{align}\\
さらに、開始が-5分であるため\\
18.6[min]

体感で20分ぐらい経ってから取得した値なので、それなりに合ってそう。

結論

みんな大好き、オーバーフローには気をつけようね!!(雑)

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4