/dev/randomと/dev/urandom


/dev/randomと/dev/urandom(これで最後)は、乱数を発生させるデバイスで、エントロピ生成機と称する入力デバイス(/proc/input下のデバイス)割り込みタイミングをベースに、乱数を発生させるようです。なお/dev/randomは完全にエントロピ生成機をベースにしており、従ってマウス/キーボードの入力割り込みがない場合、その割り込みが発生するまで、ブロックされます。 /dev/randomをcatで読み出すと、キーボード/マウスを動作させないと停まってしまうのはそのためです。(キーボード/マウスの操作はリモート端末ではダメです。)

なお、割り込みハンドらのstruct irqaction* action->flagsにIRQF_SAMPLE_RANDOMを設定することで、入力デバイス以外の割り込みデバイスでも、乱数のベースにすることができるようです。

/dev/urandomもエントロピ生成機をベースにしていますが、割り込みが発生していない場合、前回の情報をベースにハッシュにて乱数を生成しているようです。従ってブロックされることがありません。

入力割り込み毎に前回の割り込みとの時間差をベースにして、エントロピープールに蓄えて、実際の乱数発生時は、このプールからセコンドプールに転送して、そこから乱数を生成しているようです。たぶんメインプールに蓄え時は、プリエンプと禁止する必要があり、パフォーマンスの兼ね合いじゃないでしょうか?この辺りのこととか、数学的(?)な事もあってか、実装はわかりません。

とりあえず、エントロピーのベースとなる、割り込みからの処理です。入力デバイスからの割り込み毎に、add_input_randomness()がコールされ、そこからadd_timer_randomness()してエントロピーの計算をしているようです。
void add_input_randomness(unsigned int type, unsigned int code,
                                unsigned int value)
{
       static unsigned char last_value;

       /* ignore autorepeat and the like */
       if (value == last_value)
               return;

       DEBUG_ENT("input event\n");
       last_value = value;
       add_timer_randomness(&input_timer_state,
                            (type << 4) ^ code ^ (code >> 4) ^ value);
}
なんか良くわかりませんが、雰囲気、前回の割り込みと今回の割り込みの時間差(jiffies値)をdelta、前回のdeltaと今回のdeltaの差をdelta2、前回のdelta2と今回のdelta2の差をdelta3とし、その絶対値の小さい物を、credit_entropy_bit()の引数として、エントロピーの処理としているようですが・・・。
static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
{
       struct {
               long jiffies;
               unsigned cycles;
               unsigned num;
       } sample;
       long delta, delta2, delta3;

       preempt_disable();
       /* if over the trickle threshold, use only 1 in 4096 samples */
       if (input_pool.entropy_count > trickle_thresh &&
           ((__this_cpu_inc_return(trickle_count) - 1) & 0xfff))
               goto out;

       sample.jiffies = jiffies;

       if (!arch_get_random_int(&sample.cycles))
               sample.cycles = get_cycles();

       sample.num = num;
       mix_pool_bytes(&input_pool, &sample, sizeof(sample));


       if (!state->dont_count_entropy) {
               delta = sample.jiffies - state->last_time;
               state->last_time = sample.jiffies;

               delta2 = delta - state->last_delta;
               state->last_delta = delta;

               delta3 = delta2 - state->last_delta2;
               state->last_delta2 = delta2;

               if (delta < 0)
                       delta = -delta;
               if (delta2 < 0)
                       delta2 = -delta2;
               if (delta3 < 0)
                       delta3 = -delta3;
               if (delta > delta2)
                       delta = delta2;
               if (delta > delta3)
                       delta = delta3;

               credit_entropy_bits(&input_pool,
                                   min_t(int, fls(delta>>1), 11));
       }
out:
       preempt_enable();
}


最終更新 2012/07/08 20:11:31 - north
(2012/07/08 20:11:31 作成)


検索

アクセス数
3575118
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。