名前
sched - スケジューリング API の概要説明
API の概要
Linux のスケジューリング API は以下のとおりである。- sched_setscheduler(2)
- 指定されたスレッドのスケジューリングポリシーとパラメーターを設定する。
- sched_getscheduler(2)
- 指定されたスレッドのスケジューリングポリシーを返す。
- sched_setparam(2)
- 指定されたスレッドのスケジューリングパラメーターを設定する。
- sched_getparam(2)
- 指定されたスレッドのスケジューリングパラメーターを取得する。
- sched_get_priority_max(2)
- 指定されたスケジューリングポリシーで利用可能な最小の優先度を返す。
- sched_get_priority_min(2)
- 指定されたスケジューリングポリシーで利用可能な最大の優先度を返す。
- sched_rr_get_interval(2)
- 「ラウンドロビン」スケジューリングポリシーでスケジューリグされるスレッドで使用される単位時間 (quantum) を取得する。
- sched_yield(2)
- 呼び出し元が CPU の使用権を明け渡して、 他のスレッドが実行できるようにする。
- sched_setaffinity(2)
- (Linux 固有) 指定されたスレッドの CPU affinity を設定する。
- sched_getaffinity(2)
- (Linux 固有) 指定されたスレッドの CPU affinity を取得する。
- sched_setattr(2)
- 指定されたスレッドのスケジューリングポリシーとパラメーターを設定する。 この (Linux 固有の) システムコールは sched_setscheduler(2) と sched_setparam(2) の両方の機能を持つ。
- sched_getattr(2)
- 指定されたスレッドのスケジューリングポリシーとパラメーターを取得する。 この (Linux 固有の) システムコールは sched_getscheduler(2) と sched_getparam(2) の両方の機能を持つ。
スケジューリングポリシー (scheduling policy)
スケジューラ (scheduler) とはカーネルの構成要素で、 次に CPU で実行される実行可能なスレッドを決定するものである。 各々のスレッドには、スケジューリングポリシーと 「静的」なスケジューリング優先度 sched_priority が対応付けられる。 スケジューラは、システム上の全スレッドのスケジューリングポリシーと 静的優先度に関する知識に基づいて決定を行う。SCHED_FIFO: ファーストインファーストアウトスケジューリング
SCHED_FIFO は 0 より大きな静的優先度でのみ使用できる。このポリシーでは、 SCHED_FIFO スレッドが実行可能になった場合、 そのポリシーが SCHED_OTHER、 SCHED_BATCH、 SCHED_IDLE の 現在実行中のスレッドは直ちに実行権を取り上げられる。 SCHED_FIFO は時分割のない単純なスケジューリングアルゴリズムである。 SCHED_FIFO ポリシーでスケジューリングされているスレッドには以下の ルールが適用される:- *
- より高い優先度の他のスレッドによって取って代わられた SCHED_FIFO スレッドはその優先度のリストの先頭に留まり続け、 より高い優先度のスレッド全てが停止 (block) した場合に実行を再開する。
- *
- SCHED_FIFO スレッドが実行可能になった時、その優先度のリストの最後 に挿入される。
- *
- sched_setscheduler(2), sched_setparam(2), sched_setattr(2) は pid で指定された SCHED_FIFO (または SCHED_RR) スレッドが 実行可能な場合、リストの最初に置く。 結果として、もし優先度が同じだった場合、 現在実行中のスレッドに先んじるかもしれない。 (POSIX.1-2001 ではスレッドはリストの最後に行くべきと規定されている。)
- *
- sched_yield(2) を呼び出したスレッドはリストの最後に置かれる。
SCHED_RR: ラウンドロビン (round-robin) スケジューリング
SCHED_RR は SCHED_FIFO の単純な拡張である。 上述された SCHED_FIFO に関する記述は全て SCHED_RR に 適用できる。異なるのは それぞれのスレッドは最大時間単位までしか実行できない ということである。 SCHED_RR スレッドが時間単位と同じかそれより 長い時間実行されると、 その優先度のリストの最後に置かれる。 より高い優先度のスレッドによって 置きかえられ、その後実行を再開した SCHED_RR スレッドは、そのラウンド ロビン時間単位を完全に使い切る まで実行される。その時間単位の長さは sched_rr_get_interval(2) を使って取得できる。SCHED_DEADLINE: 散発タスクモデルのデッドラインスケジューリング
バージョン 3.14 以降では、 Linux はデッドラインスケジューリングポリシー ( SCHED_DEADLINE) が提供される。 現在のところ、 このポリシーは GEDF (Global Earliest Deadline First) を使って CBS (Constant Bandwidth Server) との組み合わせで実装されている。 このポリシーと関連する属性の設定、取得を行うには、 Linux 固有のシステムコール sched_setattr(2) と sched_getattr(2) を使用する必要がある。arrival/wakeup absolute deadline | start time | | | | v v v -----x--------xooooooooooooooooo--------x--------x--- |<- comp. time ->| |<------- relative deadline ------>| |<-------------- period ------------------->|
arrival/wakeup absolute deadline | start time | | | | v v v -----x--------xooooooooooooooooo--------x--------x--- |<-- Runtime ------->| |<----------- Deadline ----------->| |<-------------- Period ------------------->|
sched_runtime <= sched_deadline <= sched_period
SCHED_OTHER: Linux のデフォルトの時分割スケジューリング
SCHED_OTHER は静的優先度 0 でのみ使用できる。 SCHED_OTHER は Linux 標準の時分割スケジューラで、 特別なリアルタイム機構を必要としていない全てのスレッドで使用される。 実行するスレッドは、静的優先度 0 のリストから、このリストの中だけで 決定される「動的な」優先度 (dynamic priority) に基いて決定される。 動的な優先度は ( nice(2), setpriority(2), sched_setattr(2) により設定される) nice 値に基づいて決定されるもので、 単位時間毎に、スレッドが実行可能だが、スケジューラにより実行が拒否された 場合にインクリメントされる。 これにより、全ての SCHED_OTHER スレッドでの公平性が保証される。SCHED_BATCH: バッチプロセスのスケジューリング
(Linux 2.6.16 以降) SCHED_BATCH は静的優先度 0 でのみ使用できる。 このポリシーは (nice 値に基づく) 動的な優先度にしたがってスレッドの スケジューリングが行われるという点で、 SCHED_OTHER に似ている。 異なるのは、このポリシーでは、スレッドが常に CPU に負荷のかかる (CPU-intensive) 処理を行うと、スケジューラが仮定する点である。 スケジューラはスレッドを呼び起こす毎にそのスレッドにスケジューリング上の ペナルティを少し課し、その結果、このスレッドはスケジューリングの決定で 若干冷遇されるようになる。SCHED_IDLE: 非常に優先度の低いジョブのスケジューリング
(Linux 2.6.23 以降) SCHED_IDLE は静的優先度 0 でのみ使用できる。 このポリシーではプロセスの nice 値はスケジューリングに影響を与えない。子プロセスでのスケジューリングポリシーのリセット
各スレッドには reset-on-fork スケジューリングフラグがある。 このフラグがセットされると、 fork(2) で作成される子プロセスは特権スケジューリングポリシーを継承しない。 reset-on-fork フラグは以下のいずれかの方法でセットできる。- *
- sched_setscheduler(2) を呼び出す際に SCHED_RESET_ON_FORK フラグを policy 引き数に論理和で指定する (Linux 2.6.32 以降)。
- *
- sched_setattr(2) を呼び出し際に attr.sched_flags に SCHED_FLAG_RESET_ON_FORK フラグを指定する。
- *
- 呼び出したスレッドのスケジューリングポリシーが SCHED_FIFO か SCHED_RR の場合、子プロセスのポリシーは SCHED_OTHER にリセットされる。
- *
- 子プロセスが負の nice 値を持っている場合、子プロセスの nice 値は 0 にリセットされる。
特権とリソース制限
2.6.12 より前のバージョンの Linux カーネルでは、 特権スレッド ( CAP_SYS_NICE ケーパビリティを持つスレッド) だけが 0 以外の静的優先度を設定する (すなわち、リアルタイムスケジューリングポリシーを設定する) ことができる。 非特権スレッドができる変更は SCHED_OTHER ポリシーを設定することだけであり、さらに、 この変更を行えるのは、 呼び出し元の実効ユーザー ID がポリシーの変更対象スレッド ( pid で指定されたスレッド) の実ユーザー ID か実効ユーザー ID と 一致する場合だけである。- *
- 非特権スレッドに 0 以外の RLIMIT_RTPRIO ソフトリミットが設定されている場合、 非特権スレッドはそのスレッドのスケジューリングポリシーと優先度を 変更できるが、優先度を現在の自身の優先度と RLIMIT_RTPRIO ソフトリミットの大きい方よりも高い値に設定できないという制限が課される。
- *
- RLIMIT_RTPRIO ソフトリミットが 0 の場合、優先度を下げるか、 リアルタイムでないポリシーへ切り替えるかの変更だけが許可される。
- *
- ある非特権スレッドが別のスレッドに対してこれらの変更を行う際にも、 同じルールが適用される。変更を行えるのは、変更を行おうとするスレッド の実効ユーザー ID が変更対象のスレッドの実ユーザー ID か実効ユーザー ID と 一致している場合に限られる。
- *
- SCHED_IDLE ポリシーの場合には特別なルールが適用される。 2.6.39 より前の Linux カーネルでは、このポリシーで動作する非特権スレッドは、 RLIMIT_RTPRIO リソース上限の値に関わらず、自分のポリシーを変更することができない。 2.6.39 以降の Linux カーネルでは、非特権スレッドは、自分の nice 値が RLIMIT_NICE リソース上限 ( getrlimit(2) 参照) で許可された範囲である限りは、自分のスケジューリングポリシーを SCHED_BATCH か SCHED_NORMAL ポリシーに切り替えることができる。
リアルタイムプロセスとデッドラインプロセスの CPU 使用量を制限する
SCHED_FIFO, SCHED_RR, SCHED_DEADLINE でスケジューリングされる スレッドが停止せずに無限ループに陥ると、 他の全てのより低い優先度のスレッドを永久に停止 (block) させてしまう。 Linux 2.6.25 より前では、 リアルタイムプロセスが暴走してしまい、システムが止まってしまうのを防止する唯一の方法は、 (コンソールで) シェルをテスト対象のアプリケーションよりも高い静的優先度で実行することだけであった。 これによって期待通りに停止したり終了したりしないリアルタイム アプリケーションを緊急終了させることが可能になる。- /proc/sys/kernel/sched_rt_period_us
- このファイルは、 CPU 時間 100% にあたるスケジューリング間隔を指定する。 このファイルの値として 1 から INT_MAX を指定できる。 この値は実際の時間としては 1 マイクロ秒から約 35 分に相当する。 このファイルのデフォルト値は 1,000,000 (1 秒) である。
- /proc/sys/kernel/sched_rt_runtime_us
- このファイルの値は、 システム上のリアルタイムスケジューリングやデッドラインスケジューリングの全プロセスが使用できる「期間」を指定する。 このファイルの値として -1 から INT_MAX-1 を指定できる。 -1 を指定すると、実行時間 (runtime) はスケジューリング間隔 (period) と同じになる。 つまり、 CPU 時間はリアルタイムでないプロセスには確保されない (カーネル 2.6.25 より前の Linux の動作である)。 このファイルのデフォルト値は 950,000 (0.95 秒) である。 これは CPU 時間の 5% がリアルタイムやデッドラインスケジューリングポリシー以外で動作するプロセスに確保されるという意味する。
応答時間 (response time)
I/O 待ちで停止したより高い優先度のスレッドは再びスケジューリングされる 前にいくらかの応答時間がかかる。デバイスドライバーを書く場合には "slow interrupt" 割り込みハンドラーを使用することで この応答時間を劇的に減少させることができる。その他
子プロセスは fork(2) の際に親プロセスのスケジューリングポリシーとパラメーターを継承する。 execve(2) の前後で、スケジューリングポリシーとパラメーターは保持される。注意
もともとは、標準の Linux は一般目的のオペレーティングシステムとして 設計されており、バックグラウンドプロセスや対話的アプリケーション、 リアルタイム性の要求が厳しくないリアルタイムアプリケーション (普通はタイミングの応答期限 (deadline) を満たす必要があるアプリケーション) を扱うことができた。 Linux カーネル 2.6 では、 カーネルのプリエンプション (タスクの置き換え) が可能であり、 新たに導入された O(1) スケジューラにより、 アクティブなタスクの数に関わらずスケジューリングに必要な時間は 固定で確定的 (deterministic) であることが保証されている。 それにも関わらず、カーネル 2.6.17 までは 真のリアルタイムコンピューティングは実現できなかった。本流の Linux カーネルでのリアルタイム機能
カーネル 2.6.18 から現在まで、 Linux は徐々にリアルタイム機能を備えつつ あるが、 これらの機能のほとんどは、 Ingo Molnar, Thomas Gleixner, Steven Rostedt らによって開発された、 以前の realtime-preempt パッチ からのものである。 これらのパッチが本流のカーネルに完全にマージされるま では (マージの完了はカーネル 2.6.30 あたりの予定)、 最高のリアルタイム 性能を達成するには realtime-preempt パッチを 組み込まなければならない。 これらのパッチはpatch- kernelversion-rtpatchversion
という名前で、 http://www.kernel.org/pub/linux/kernel/projects/rt/ からダウンロードできる。
関連項目
chrt(1), taskset(1), getpriority(2), mlock(2), mlockall(2), munlock(2), munlockall(2), nice(2), sched_get_priority_max(2), sched_get_priority_min(2), sched_getscheduler(2), sched_getaffinity(2), sched_getparam(2), sched_rr_get_interval(2), sched_setaffinity(2), sched_setscheduler(2), sched_setparam(2), sched_yield(2), setpriority(2), pthread_getaffinity_np(3), pthread_setaffinity_np(3), sched_getcpu(3), capabilities(7), cpuset(7) Programming for the real world - POSIX.4 by Bill O. Gallmeister, O'Reilly & Associates, Inc., ISBN 1-56592-074-0. Linux カーネルソースのファイル Documentation/scheduler/sched-deadline.txt, Documentation/scheduler/sched-rt-group.txt, Documentation/scheduler/sched-design-CFS.txt, Documentation/scheduler/sched-nice-design.txtこの文書について
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2014-10-02 | Linux |