プロセスの優先度
通常のプロセス(非リアルタイムプロセス)には静的優先度と動的優先度の2種類の優先度がある。
静的/動的優先度どちらとも値が小さい方が優先度が高い。
静的優先度はプロセスのnice値により固定的に決まる。niceは-20〜19の値を取るが、これをそのまま100〜139にずらした値が静的優先度となる。
動的優先度はtask_structのprioに格納される。
動的優先度はtopコマンドのPRIフィールドで確認できる。ただし、カーネル内で使用している値100〜139が0〜39にずらされて表示されている。
計算式は以下の通りでstatic_prioからボーナス(bonus)値を減算している。(プライオリティを減算して優先度を上げることから「ボーナス」と呼んでいると思われる)
CURRENT_BONUS()はプロセスのsleep_avgからボーナスを算出する。計算式は以下の通りでsleep_avgの割合いに応じて、0〜MAX_BONUSの値になる。sleep_avgがMaxだとボーナスは最大のMAX_BONUSとなる。
MAX_BONUSは通常のプロセスの優先度が取りうる値の範囲の25%になるように設定されている。具体的には通常プロセスの優先度は100〜139で幅40。これの25%なのでMAX_BONUSは10になる。
よってsleep_avgとボーナスの関係は以下のようになっている。
ボーナスの値の範囲をプロセス優先度の範囲の25%としているのは、sched.cのコメントによると以下のため。
ボーナス幅が25%で-5〜5になっていれば、nice 19のプロセスは最大でもnice14相当までしか優先度が上がらないので、プリエンプトしてしまうことはないし、nice -20のプロセスは最悪でもnice -15相当までしか優先度が下がらないのでnice 0 のプロセスにプリエンプトされることはない。
Sleepしていると増えて(*1)、CPUを使っていると減っていく(*2)。
(*1) Wakeupされて、schedule()で初めて実行プロセスとして選ばれると、recalc_task_prio()でSleepしていた時間が加算される。
(*2) schedule()で他のプロセスに切り替わるときに、使用したCPU時間を減算している。
5. 実際の動的優先度の変化
topコマンドで実際にプロセスの動的優先度がどのように変化するかを見て、3.の計算を確認してみた。
普通にコマンドを実行した時のプロセスはnice 0なので静的優先度は120になり、これにボーナス値(-5〜5)が減算されることになる。
ケース1 - while(1);のようにしてひたすらCPUを使うプロセスを実行
ケース2 - ほとんどがsleep()しているプロセスを実行
nice値が小さいとマウスカーソルの動きが鈍くなる。
<--time_sliceが大きくなってなかなかExpireしないから???
静的/動的優先度どちらとも値が小さい方が優先度が高い。
1. 静的優先度
静的優先度は0〜139の値を取る。このうち、0〜99はリアルタイムプロセスに使用される。通常のプロセスは100〜139になる。静的優先度はプロセスのnice値により固定的に決まる。niceは-20〜19の値を取るが、これをそのまま100〜139にずらした値が静的優先度となる。
nice値と静的優先度の対応
nice値 -20 ... 0 ... 19静的優先度はtask_structのstatic_prioに格納される。
静的優先度 100 ... 120 ... 139
2. 動的優先度
動的優先度は静的優先度をベースにCPU使用量に基づいて算出される。スケジューラによるプロセスの選択時には動的優先度が使用される。取り得る値の範囲は静的優先度と同じ100〜139。動的優先度はtask_structのprioに格納される。
動的優先度はtopコマンドのPRIフィールドで確認できる。ただし、カーネル内で使用している値100〜139が0〜39にずらされて表示されている。
動的優先度 100 ... 120 ... 139
topの表示 0 ... 20 ... 39
3. 動的優先度の計算
effective_prio()によって、静的優先度(static_prio)をベースに計算される。計算式は以下の通りでstatic_prioからボーナス(bonus)値を減算している。(プライオリティを減算して優先度を上げることから「ボーナス」と呼んでいると思われる)
bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
prio = p->static_prio - bonus;
CURRENT_BONUS()はプロセスのsleep_avgからボーナスを算出する。計算式は以下の通りでsleep_avgの割合いに応じて、0〜MAX_BONUSの値になる。sleep_avgがMaxだとボーナスは最大のMAX_BONUSとなる。
sleep_avg実際にはCURRENT_BONUS()の値から MAX_BONUS/2を減算することで、ボーナスの範囲を-MAX_BONUS〜MAX_BONUSの範囲にずらして使用する。ボーナスが正の値だと動的優先度は上がり(ボーナス)、負の値だと動的優先度は下がる(ペナルティ)。
MAX_BONUS * --------------
MAX_SLEEP_AVG
MAX_BONUS:ボーナスの最大値
MAX_SLEEP_AVG:sleep_avgの上限値
MAX_BONUSは通常のプロセスの優先度が取りうる値の範囲の25%になるように設定されている。具体的には通常プロセスの優先度は100〜139で幅40。これの25%なのでMAX_BONUSは10になる。
よってsleep_avgとボーナスの関係は以下のようになっている。
sleep_avg [0 ... MAX_SLEEP_AVG]
bonus [-5 ... 5 ]
ボーナスの値の範囲をプロセス優先度の範囲の25%としているのは、sched.cのコメントによると以下のため。
1) nice 19のプロセスがnice 0のプロセスをプリエンプトしないようにする
2) nice -20のプロセスがnice 0のプロセスにプリエンプトされないようにする
2) nice -20のプロセスがnice 0のプロセスにプリエンプトされないようにする
ボーナス幅が25%で-5〜5になっていれば、nice 19のプロセスは最大でもnice14相当までしか優先度が上がらないので、プリエンプトしてしまうことはないし、nice -20のプロセスは最悪でもnice -15相当までしか優先度が下がらないのでnice 0 のプロセスにプリエンプトされることはない。
4. sleep_avg
sleep_avgはプロセスのSleep量を示し(0〜NS_MAX_SLEEP_AVG)、動的優先度の計算で使用される。Sleepしていると増えて(*1)、CPUを使っていると減っていく(*2)。
(*1) Wakeupされて、schedule()で初めて実行プロセスとして選ばれると、recalc_task_prio()でSleepしていた時間が加算される。
(*2) schedule()で他のプロセスに切り替わるときに、使用したCPU時間を減算している。
5. 実際の動的優先度の変化
topコマンドで実際にプロセスの動的優先度がどのように変化するかを見て、3.の計算を確認してみた。普通にコマンドを実行した時のプロセスはnice 0なので静的優先度は120になり、これにボーナス値(-5〜5)が減算されることになる。
ケース1 - while(1);のようにしてひたすらCPUを使うプロセスを実行
結果:実行直後PRIは20で、そのうち25になった。
20は優先度120に対応する表示値。最初はbonusが0で動的優先度が基本値(静的優先度)の値を取っていたのが、CPUをどんどん使うことでsleep_avgが0になり、結果、bonusが-5になって動的優先度が25になっている。
20は優先度120に対応する表示値。最初はbonusが0で動的優先度が基本値(静的優先度)の値を取っていたのが、CPUをどんどん使うことでsleep_avgが0になり、結果、bonusが-5になって動的優先度が25になっている。
ケース2 - ほとんどがsleep()しているプロセスを実行
結果:PRIが16になった。
ほとんどCPUを使用しないので、sleep_avgがほぼ最大値になり、結果bonusがほぼ最大値の4になり動的優先度が16になっている。
nice値が小さいとマウスカーソルの動きが鈍くなる。
<--time_sliceが大きくなってなかなかExpireしないから???
INTERACTIVEになりやすいせいもある?