プロセススケジューリング

スケジューラは プロセスとスレッドを全く区別せずに扱う。実行可能なプロセス(スレッド)は下図のRUNキューにリンクされている。スケジューラはこのRUNキューに継っているプロセスのうち最も高い優先度を持つプロセスを選び出しCPU(実行権)を与える。現在実行中のプロセスはcurrentというポインタにより指されている。

何も実行するプロセスがなくなると、スケジューラはidleと呼ばれる何もしないプロセスに実行権を渡す。

img4.gif
  schedule()
     タスクキューtq_schedulerの実行(run_task_queue関数) <詳しくは後述>
     BHハンドラ呼び出し(do_bottom_half関数) <詳しくは後述>
     プリエンプション要求をクリア
     if(スケジューラを呼び出したプロセスの状態がTASK_RUNNINGでない){
           プロセスをRUNキューから外す(del_from_runqueue関数)
     }
     while(RUNキューに継っている全てのプロセスに対して) {
           最も高いプライオリティのプロセスを探す(goodness関数)
     }
     while(システム上の全てのプロセスに対して) {
           プライオリティ再計算
     }
     プロセスコンテキストの切替え(switch_to関数)

走行中のプロセスが待ちに入る場合、待ち対象のオブジェクト毎に用意されているwaitキューに自分自身を繋ぎCPUを放棄する。(自分自身をRUNキューからはずし、スケジューラを呼び出す) sleep_on関数、interruptible_sleep_on関数が用意されている。この二つの関数の違いは、WAIT状態になったときのプロセスがシグナルにより起床するかしないかという点である。

img5.gif
  sleep_on(WAITキュー) (または、interruptible_sleep_on(WAITキュー))
        スタック上にwait_queueを用意
        カレントプロセスの状態をTASK_UNINTERRUPTIBLEに変更
            (interruptible_sleep_onの時はTASK_INTERRUPTIBLE)
        wait_queueにカレントタスクを登録。
        WAITキューにwait_queueをリンク(add_wait_queue関数)
        スケジューラを呼び出してCPUを放棄する(schedule関数)
        WAITキューからwait_queueを外す(remove_wait_queue関数)

このプロセスはイベントの発生により起床される。(wake_up関数、wake_up_interruptible関数)起床されたばかりのプロセスはRUNキュー継っているが、waitキューの方にも継ったままになっている。このプロセスは再度実行権が与えられた時に、まず最初に自分自身をwaitキューから外す処理を行う。

この方式のメリットは、割り込みハンドラなどの延長でプロセス起床を行う場合、waitキューの操作を行わないで良く、排他処理を単純化できるところにある。

img6.gif
   wake_up(WAITキュー) (または、wake_up_interruptible(qhead))
        while(WAITキューで待っている全てのプロセスに対し) {
             wake_upの場合は全てのプロセスを起床(wake_up_process関数)
             wake_up_interruptibleの場合は、状態がTASK_INTERRUPTIBLEな
                 プロセスのみを起床(wake_up_process関数)
        }

   wake_up_process(プロセス)
        プロセスの状態をTASK_RUNNINGに変更
        if(このプロセスが、まだRUNキューに継っていないなら)
              RUNキューにつなぐ(add_to_runqueue関数)
              再スケジューリング要求(reschedule_idle関数)
        }

 

(NIS)HirokazuTakahashi
2000年06月11日 (日) 22時29分57秒 JST
1