短い答え
99 がリアルタイム優先の勝者となります。
PR は優先レベルです (範囲 -100 から 39)。 PR が低いほど、プロセスの優先度が高くなります。
PR は次のように計算されます:
- 通常のプロセスの場合:PR =20 + NI (NI は適切で、-20 から 19 の範囲)
- リアルタイム プロセスの場合:PR =- 1 - real_time_priority (real_time_priority の範囲は 1 から 99)
長文
プロセスには 2 種類あり、通常 ものとリアルタイム 通常のもの (およびそれらのみ) の場合、nice は次のように適用されます:
いいね
「良さ」のスケールは -20 から 19 まであり、-20 が最高の優先度で、19 が最低の優先度です。優先度は次のように計算されます:
PR =20 + NI
NI はナイス レベル、PR はプライオリティ レベルです。ご覧のとおり、-20 は実際には 0 にマップされ、19 は 39 にマップされます。
デフォルトでは、プログラムのナイス値は 0 ビットです。root ユーザーは、次のコマンドを使用して指定されたナイス値でプログラムを起動できます:
nice -n <nice_value> ./myProgram
リアルタイム
さらに先に進むことができました。 nice 優先順位は、実際にはユーザー プログラムに使用されます。 UNIX/LINUX の全体的な優先度の値の範囲は 140 ですが、nice 値を使用すると、プロセスは範囲の最後の部分 (100 から 139) にマップできます。この方程式は、負の PR レベル (-100 から -1) に対応する 0 から 99 までの値を到達不能のままにします。これらの値にアクセスできるようにするには、プロセスを「リアルタイム」と表現する必要があります。
LINUX 環境には、次のコマンドで表示できる 5 つのスケジューリング ポリシーがあります:
chrt -m
次のリストが表示されます:
1. SCHED_OTHER the standard round-robin time-sharing policy
2. SCHED_BATCH for "batch" style execution of processes
3. SCHED_IDLE for running very low priority background jobs.
4. SCHED_FIFO a first-in, first-out policy
5. SCHED_RR a round-robin policy
スケジューリング プロセスは、通常のスケジューリング ポリシー (1 ~ 3) とリアルタイム スケジューリング ポリシー (4 および 5) の 2 つのグループに分けることができます。リアルタイム プロセスは、通常のプロセスより常に優先されます。次のコマンドを使用して、リアルタイム プロセスを呼び出すことができます (例は、SCHED_RR ポリシーを宣言する方法です)。
chrt --rr <priority between 1-99> ./myProgram
リアルタイム プロセスの PR 値を取得するには、次の式が適用されます。
PR =-1 - rt_prior
rt_prior は 1 から 99 までの優先度に対応します。そのため、他のプロセスよりも優先度が高いプロセスは、番号 99 で呼び出されるプロセスになります。
リアルタイム プロセスでは、nice 値は使用されないことに注意してください。
プロセスの現在の「ナイスネス」と PR 値を確認するには、次のコマンドを実行します:
top
次の出力が表示されます:
図では、PR 値と NI 値が表示されます。リアルタイム値に対応する PR 値 -51 のプロセスに注意してください。 PR値が「rt」と記載されているプロセスもあります。この値は、実際には PR 値の -100 に相当します。
sched.h のこのコメントはかなり決定的です:
/*
* Priority of a process goes from 0..MAX_PRIO-1, valid RT
* priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
* tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
* values are inverted: lower p->prio value means higher priority.
*
* The MAX_USER_RT_PRIO value allows the actual maximum
* RT priority to be separate from the value exported to
* user-space. This allows kernel threads to set their
* priority to a value higher than any user task. Note:
* MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
*/
この部分に注意してください:
プライオリティ値が反転:低い p->prio
値は優先度が高いことを意味します .
これを突き止めるために、次のような実験を行いました:
-
process1:RT 優先度 =40、CPU アフィニティ =CPU 0。このプロセスは 10 秒間「スピン」するため、優先度の低いプロセスは CPU 0 で実行されません。
-
プロセス 2:RT 優先度 =39、CPU アフィニティ =CPU 0。このプロセスは、0.5 秒ごとに標準出力にメッセージを出力し、その間はスリープします。各メッセージとともに経過時間を出力します。
PREEMPT_RT パッチを適用した 2.6.33 カーネルを実行しています。
実験を実行するには、1 つのウィンドウで (ルートとして) process2 を実行し、別のウィンドウで (ルートとして) process1 を開始します。その結果、プロセス 1 はプロセス 2 を横取りしているように見え、10 秒間実行できません。
2 番目の実験では、プロセス 2 の RT 優先度を 41 に変更します。この場合、プロセス 2 は not です。 process1 によってプリエンプトされました。
この実験は、大きい sched_setscheduler()
の RT プライオリティ値 の優先度が高くなります。これは Michael Foukarakis が sched.h から指摘したことと矛盾しているように見えますが、実際にはそうではありません。カーネル ソースの sched.c には、次のものがあります。
static void
__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
{
BUG_ON(p->se.on_rq);
p->policy = policy;
p->rt_priority = prio;
p->normal_prio = normal_prio(p);
/* we are holding p->pi_lock already */
p->prio = rt_mutex_getprio(p);
if (rt_prio(p->prio))
p->sched_class = &rt_sched_class;
else
p->sched_class = &fair_sched_class;
set_load_weight(p);
}
rt_mutex_getprio(p) は次のことを行います:
return task->normal_prio;
normal_prio() はたまたま次のことを行います:
prio = MAX_RT_PRIO-1 - p->rt_priority; /* <===== notice! */
...
return prio;
言い換えると、(私自身の解釈):
p->prio = p->normal_prio = MAX_RT_PRIO - 1 - p->rt_priority
わお!それは紛らわしいです!要約すると:
-
p->prio を使用すると、小さい値が大きい値より優先されます。
-
p->rt_priority を使用すると、値が大きいほど値が小さくなります。これは、
sched_setscheduler()
を使用して設定されたリアルタイムの優先度です。 .