-
スケジューラから見たOSの話
2009.06.22
warawara@bug.co.jp
-
この資料での用語
CPU
kernelからCPUとして見えるもの
今回はメモリ周りには触れないこともあり、
ProcessもThreadもTaskもひっくるめてタスクと表現
タスク
OS
kernelを指す。
例)Windows XP:NT kernel
MacOS X:mach
-
OSって何?
OSの2つの大きな仕事
タスクのスケジューリング
メモリを主としたリソース管理
-
スケジューラの仕事
タスクをどう公平に実行するか
タスクへのCPU時間割当方法
どのCPUで実行するか
どのメモリで実行するか
-
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
どのCPUで実行?
どのメモリで実行?
Cache, MMU, NUMA, Xenなどは
また別のお話
-
まずは
-
シングルタスク
while(1)
{
入力待ち
出力
}
-
シングルタスク
Task-A
時間
割込
-
シングルタスク
Task-A
時間
割込1
割込2
-
シングルタスク
Task-A
時間
-
シングルタスク
Task-A
時間
割込1
割込2
-
シングルタスク
Task-A
時間
割込1
割込2
割込の優先度によって、ある程度のマルチタスクっぽい処理は可能
・リソースが極端に少ない場合
・単機能な場合
・リアルタイム性を非常に求められる場合
など
-
シングルタスク
MS-DOS系
組込みOSなし案件
-
次に
-
複数のタスクを動かそう
-
どうやって?
イベント駆動
時分割動作
イベント駆動+時分割
-
どうやって?
イベント駆動
時分割動作
イベント駆動+時分割
-
イベント駆動
while(1)
{
イベントチェック
出力
}
処理
Task A
処理
Task B
処理
Task B
イベントキュー
-
イベント駆動
Task-A
時間
Task-B
Task-C
-
イベント駆動
Task-A
時間
Task-B
Task-C
自主的な遷移
-
イベント駆動
Task-A
時間
Task-B
Task-C
自主的な遷移
問題点
各タスクが思いやりをもって処理を返さないと全体が止まってしまう
-
イベント駆動
Windows 3.1系
System7.0, MacOS8~9
PalmOS
non-preemptiveなマルチタスク
Protothreads
Windows 1.0/2.x/3.x
μITRON
Switch-caseをうまく利用してマルチタスクっぽく動く
-
どうやって?
イベント駆動
時分割動作
イベント駆動+時分割
-
時分割動作
タイマーハンドラ
処理
Task A
処理
Task B
処理
Task B
タイマー割込
-
時分割動作
Task-A
時間
Task-B
Task-C
-
時分割動作
Task-A
時間
Task-B
Task-C
強制的な遷移
-
時分割動作
Thread Manager(System7.5〜)
これのおかげでシングルタスクとして書かれたアプリもPreemptiveかのように振舞う
-
どうやって?
イベント駆動
時分割動作
イベント駆動+時分割
-
イベント駆動+時分割
Task-A
時間
Task-B
Task-C
-
イベント駆動+時分割
Task-A
時間
Task-B
Task-C
自主的な遷移
時間切れによる強制的な遷移
-
イベント駆動+時分割
Windows 9x系
Windows NT系
MacOS X(mach)
preemptiveなmultitask
UNIX/Linux系
RTOS系
Windows 95/98/Me
Windows NT3.x/4.0/2000/Xp/Vista/7
SVR4, 4.4BSD, ...
VxWorks, QNX, ThreadX, ...
... 最近のはすべて
-
改善してみよう
-
改善キーワード
タスクの優先度
割当時間(クォンタム)
リアルタイム性
スケジューリング負荷
割込処理
タイムスライスとも言う
-
改善キーワード
タスクの優先度
割当時間(クォンタム)
リアルタイム性
スケジューリング負荷
割込処理
-
タスクの優先度
タスクには優先順位がある
課題を提出しなきゃ
トイレ行きたい...
温泉行きたいなぁ...
高い
低い
優先度の高いタスクほど先に動かす
-
タスクの優先度
Task-A
時間
Task-B
Task-C
Task-D
!
!
!
!
!
!
!
高い
低い
!
!
!
優先度の高いタスクほど先に動かす
!
!
!
!
!
!
!
!
!
!
!
-
タスクの優先度
Task-A
時間
Task-B
Task-C
Task-D
!
!
!
!
!
!
!
高い
低い
!
!
!
優先度の高いタスクほど先に動かす
!
!
!
!
!
!
!
!
!
!
!
優先度の高いタスクが動ける間は、優先度の低いタスクには処理は回ってこない
-
タスクの優先度
・FIFO型
・Round Robin型
Task D
Task C
Task B
Task A
順番待ち
Task D
Task C
Task B
Task A
順番待ち
タスクの優先度
優先度が同じ場合は?
-
タスクの優先度
以上、静的な優先度の話
-
タスクの優先度
I/Oバウンドなタスクかどうか
ユーザが変更する(nice値)
優先度を動的に変えてみる
ユーザと対話型のタスクは優先度をあげる
ビルドなど対話型でないタスクは優先度を下げる
プログラムから優先度を変更する
-
タスクの優先度
I/Oバウンドなタスクかどうか
ユーザが変更する(nice値)
優先度を動的に変えてみる
ユーザと対話型のタスクは優先度をあげる
ビルドなど対話型でないタスクは優先度を下げる
プログラムから優先度を変更する
I/Oバウンド
I/Oにより起こされることの多いタスク(ユーザをイライラさせないためには、キー入力の反応は素早い方がよいよね、という話)
これに対して、
CPUバウンド
ビルドなど計算が主体のタスク
-
タスクの優先度
Task-A
時間
Task-B
Task-C
高い
低い
Sem取得
Sem待ち
優先度逆転区間
優先度逆転問題
Sem解放
-
タスクの優先度
Task-A
時間
Task-B
Task-C
高い
低い
Sem取得
Sem待ち
優先度逆転区間
優先度逆転問題
VxWorksを載せた火星探査船「マーズ・パスファインダー」ではこの優先度逆転が起こりシステムリブートを起こしたよ(1997)
Sem解放
-
改善キーワード
タスクの優先度
割当時間(クォンタム)
リアルタイム性
スケジューリング負荷
割込処理
-
割当時間
タスクに応じて使用可能な上限時間を設ける
どう割当てるかは実装次第
-
改善キーワード
タスクの優先度
割当時間(クォンタム)
リアルタイム性
スケジューリング負荷
割込処理
-
リアルタイム性
割込にどれだけ早く反応できるか
Non-preemptive kernel
Preemptive kernel
妥協 Preemptive kernel
-
リアルタイム性
Task-A
時間
Task-B
OS
Non-preemptive kernel
システムコール終了後にディスパッチ
割込
-
リアルタイム性
Task-A
時間
Task-B
OS
Preemptive kernel
割込ハンドラ終了後にディスパッチ
割込
-
リアルタイム性
Task-A
時間
Task-B
OS
妥協 Preemptive kernel
割込
割込
区間によってはシステムコールの途中でもディスパッチが可能だが、すべてのシステムコールで可能という訳ではない。
(SVR4など)
-
改善キーワード
タスクの優先度
割当時間(クォンタム)
リアルタイム性
スケジューリング負荷
割込処理
-
スケジューリング負荷
優先度の再計算頻度
次に実行するタスクを選択する方法
モノリシック vs マイクロカーネル
-
スケジューリング負荷
優先度の再計算頻度
次に実行するタスクを選択する方法
モノリシック vs マイクロカーネル
各タスクの優先度を再計算する
・クォンタムの消費具合
・I/Oバウンド型の一時的な優先度変更を元に戻す作業
・フォアグラウンドタスクか、バックグラウンドタスクか
・...
頻度が高いと負荷が増える
頻度が低いと他のタスクの応答性が悪くなる
-
スケジューリング負荷
優先度の再計算頻度
次に実行するタスクを選択する方法
モノリシック vs マイクロカーネル
・優先度ごとのReady Queue
・CPUごとのReady Queue
・選択アルゴリズム
-
スケジューリング負荷
優先度の再計算頻度
次に実行するタスクを選択する方法
モノリシック vs マイクロカーネル
Kernel空間とUser空間の行き来のコスト
MacOS X, BeOS, NeXTstep, ...
-
改善キーワード
タスクの優先度
割当時間(クォンタム)
リアルタイム性
スケジューリング負荷
割込処理
-
割込処理
割込処理タスク
ボトムハーフ
ソフトIRQ
タスクレット
(RTOS系, Solaris)
(Linux 2.2以前)
(Linux 2.4, WindowsNT系)
(Linux 2.6)
-
割込処理
割込処理タスク
ボトムハーフ
ソフトIRQ
タスクレット
(RTOS系)
(Linux 2.2以前)
(Linux 2.4, WindowsNT系)
(Linux 2.6)
割込ハンドラは、通常、処理をなるべく少なくして次の割込に備える必要があるため、最低限の処理だけを行い、後の処理は何らかの方法で他に任せる
-
割込処理
割込処理タスク
ボトムハーフ
ソフトIRQ
タスクレット
(Linux 2.2以前)
(Linux 2.4, WindowsNT系)
(Linux 2.6)
優先度の高いところにいる割込処理専用タスクにまかせる
(RTOS系, Solaris)
-
割込処理
割込処理タスク
ボトムハーフ
ソフトIRQ
タスクレット
(Linux 2.2以前)
(Linux 2.4, WindowsNT系)
(Linux 2.6)
割込ハンドラ内で関数を予約しておいて、割込処理からユーザタスクへ切り替る時に、まとめて実行する
処理時間が非常に長くなる可能性がある。
(RTOS系, Solaris)
-
割込処理
割込処理タスク
ボトムハーフ
ソフトIRQ
タスクレット
(RTOS系)
(Linux 2.2以前)
(Linux 2.4, WindowsNT系)
(Linux 2.6)
優先度の低い割込を設定して、そちらのハンドラで処理する
Linux2.4/Windows NT系のソフトIRQではリエントラントを意識してハンドラを書かなければならず大変。(ローカル割込を禁止しても別CPUに割込がかかる可能性があるため)
-
割込処理
割込処理タスク
ボトムハーフ
ソフトIRQ
タスクレット
(RTOS系)
(Linux 2.2以前)
(Linux 2.4, WindowsNT系)
(Linux 2.6)
ソフトIRQの発展
同じ種類のタスクレットは複数CPUで同時実行されないことを保証する
ネットワークパケットなど同じ種類の割り込みが多数かかることがある場合、ソフトIRQでは処理して、保留されている割り込みがあればまた処理して...を繰り返すことになるため、時間がかかってしまう可能性がある。タスクレットでは、一定数の処理を繰り返すと終了して、残りは低い優先度のカーネルスレッドに任せる。
-
具体例
-
-
4.3BSD(SVR3)の場合
1tick=10msec(通常)
動的優先度(みんな仲良く)
優先度スロット=32スロット(4つずつ)
4tick毎に現在のスレッドの優先度再計算
100tick(1sec)毎にすべてのスレッドを再計算
I/O待ち解除後は、通常のReadyキューに戻される
-
4.3BSD(SVR3)の場合
1tick=10msec(通常)
動的優先度(みんな仲良く)
優先度スロット=32スロット
4tick毎に現在のスレッドの優先度再計算
100tick(1sec)毎にすべてのスレッドを再計算
I/O待ち解除後は、通常のReadyキューに戻される
低優先度のタスクを枯渇状態に陥らせないことを保証しつつ、応答時間を改善することを目指した
-
4.3BSD(SVR3)の場合
1tick=10msec(通常)
動的優先度(みんな仲良く)
優先度スロット=32スロット
4tick毎に現在のスレッドの優先度再計算
100tick(1sec)毎にすべてのスレッドを再計算
I/O待ち解除後は、通常のReadyキューに戻される
対話型とバッチジョブのみに対応。
優先度は0〜127(小さいほど高い)
0〜49 Kernelに予約済み(Sleep優先度などに利用)
50〜127 ユーザタスク
-
4.3BSD(SVR3)の場合
1tick=10msec(通常)
動的優先度(みんな仲良く)
優先度スロット=32スロット
4tick毎に現在のスレッドの優先度再計算
100tick(1sec)毎にすべてのスレッドを再計算
I/O待ち解除後は、通常のReadyキューに戻される
動的優先度ルール
CPUの使用時間が長いほど優先度が落ちる(tick毎に加算)。この時、減衰率が固定だと(SVR3=0.5)、負荷が高い時に低い優先度に回ってこない。そのため、4.3BSDでは負荷が高いときは、減衰率を減らしている。
-
4.3BSD(SVR3)の場合
1tick=10msec(通常)
動的優先度(みんな仲良く)
優先度スロット=32スロット
4tick毎に現在のスレッドの優先度再計算
100tick(1sec)毎にすべてのスレッドを再計算
I/O待ち解除後は、通常のReadyキューに戻される
Ready Queueは4つずつの優先度をまとめたものをスロットとして扱い32スロット分のQueueを持つ。
クォンタムは100msec固定(4.3BSD)のRound Robin。
同じ優先度の他のタスクがいなければクォンタムを使い切っても実行し続ける
-
4.3BSD(SVR3)の場合
1tick=10msec(通常)
動的優先度(みんな仲良く)
優先度スロット=32スロット
4tick毎に現在のスレッドの優先度再計算
100tick(1sec)毎にすべてのスレッドを再計算
I/O待ち解除後は、通常のReadyキューに戻される
問題点
・スケーラビリティに欠ける
タスク数が膨大な時、1秒毎にすべてのタスクの優先度を再計算するのは非効率
・応答時間の保証がない
・優先度逆転が起こりえる
-
WindowsNTの場合
1tick=20msec
静的優先度+動的優先度
優先度毎のReadyキュー(0〜31)
1tick=20msec
固定優先度+動的優先度
優先度毎のReady Queue(0〜31)
-
WindowsNTの場合
1tick=20msec
静的優先度+動的優先度
優先度毎のReadyキュー(0〜31)
1tick=20msec
固定優先度+動的優先度
優先度毎のReady Queue(0〜31)
ちなみに、Windows9x系も 1tick=20msec
-
WindowsNTの場合
1tick=20msec
静的優先度+動的優先度
優先度毎のReadyキュー(0〜31)
1tick=20msec
固定優先度+動的優先度
優先度毎のReadyキュー(0〜31)
プロセスの優先度は0〜31(大きいほど高い)
0〜15 動的優先度
16〜31 固定優先度
上記が基本優先度で、それにスレッドの基本優先度(-2〜+2)が加わる。
優先度クラス 標準基本優先度
REALTIME_PRIORITY_CLASS 24
HIGH_PRIORITY_CLASS 13
NORMAL_PRIORITY_CLASS 7(background) or 9(foreground)
IDLE_PRIORITY_CLASS 4
-
WindowsNTの場合
1tick=20msec
静的優先度+動的優先度
優先度毎のReadyキュー(0〜31)
1tick=20msec
固定優先度+動的優先度
優先度毎のReady Queue(0〜31)
動的優先度ルール
優先度が0〜15のスレッドに対して以下のような場合に優先度を上げる
・ウィンドウがforegroundになった場合(backgroundになったら下げる)
・ウィンドウにたいしてマウスやキーボード入力イベントが発生した場合
・ブロック条件が満たされた場合(クォンタム毎に優先度が1ずつ下がる)
いずれも、プロセス基本優先度よりも下がることはない
-
WindowsNTの場合
1tick=20msec
静的優先度+動的優先度
優先度毎のReadyキュー(0〜31)
1tick=20msec
固定優先度+動的優先度
優先度毎のReady Queue(0〜31)
その他
スレッドの実行を特定のCPU(群)にくくりつける機能がある(スレッドアフィニティ)
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
実時間応答性の向上、ほかスケジューラの一般化を目指した
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
時分割クラス
動的優先度+Round Robin
クォンタムは優先度の低いものほど多い
実時間クラス
固定優先度+固定クォンタム
カーネルモードより優先度が高い、クォンタムは優先度の低いものほど多い
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
優先度は0〜159(大きいほど高い)
0〜59 時分割クラス
60〜99 システム優先度
100〜159 実時間クラス
(※デフォルト設定の場合)
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
動的優先度ルール(時分割クラス)
タスクの優先度再計算のタイミングは、タスクに関する特殊なイベント時に行う
・クォンタムを使い切った→優先度を下げる
・資源をブロックした→優先度を上げる
・クォンタムを使い切るのに時間がかかった→優先度を上げる
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
カーネル内にいくつかの横取り地点を設けた。
しかし、制約時間の厳しいリアルタイムには厳しい。
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
問題点
・大きな計算量を必要とするジョブを伴う対話型タスクはCPU利用率が高くなるため、
優先度が下がりやすく、結果、ユーザからの応答に遅延が生じる
・制約時間の厳しいハードリアルタイムには厳しい
・混在するアプリケーションに対してシステムを適切に調整することが難しい
-
Solaris2.6の場合
1tick=10msec(通常)
固定優先度+動的優先度
CPUごとのDispatch Queue
LWPとユーザスレッド
Preemptiveなカーネル
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
1tick=10msec(通常)
固定優先度+動的優先度
CPUごとのDispatch Queue
LWPとユーザスレッド
Preemptiveなカーネル
SVR4を元に独自実装
Solaris2.6の場合
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
1tick=10msec(通常)
固定優先度+動的優先度
CPUごとのDispatch Queue
LWPとユーザスレッド
Preemptiveなカーネル
優先度は0〜169(大きいほど高い)
0〜59 TS(Time Share)クラス, IA(Interactive)クラス
優先度は0〜169(大きいほど高い)
60〜99 SYS(System)クラス
100〜159 RT(Realtime)クラス
160〜169 割込みスレッド
Solaris2.6の場合
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
1tick=10msec(通常)
固定優先度+動的優先度
CPUごとのDispatch Queue
LWPとユーザスレッド
Preemptiveなカーネル
ユーザスレッドはスケジューラの対象にならない
ユーザスレッドはライブラリでの独自の優先度メカニズム
LWP(Light Weight Process)は明示的に作成する必要がある
Solaris2.6の場合
-
SVR4の場合
固定優先度+動的優先度
優先度毎のReadyキュー(0〜160)
半preemptiveなカーネル
優先度継承(mutex, 読み書きロック)
1tick=10msec(通常)
固定優先度+動的優先度
CPUごとのDispatch Queue
LWPとユーザスレッド
Preemptiveなカーネル
ほんの一部だけNon-preemption区間がある
・thread_create()内の一部
・pause_cpus()内の一部
・HAT, MMU処理の一部
Solaris2.6の場合
-
NORTi(μITRON4)の場合
1tick=10msec(NORTi)
固定優先度(RealTimeが大事)
優先度ごとのReadyキュー
基本FIFO型の切り替え
優先度継承(mutex)
-
NORTi(μITRON4)の場合
1tick=10msec(NORTi)
固定優先度(RealTimeが大事)
優先度ごとのReadyキュー
基本FIFO型の切り替え
優先度継承(mutex)
実時間応答性を最優先
-
NORTi(μITRON4)の場合
1tick=10msec(NORTi)
固定優先度(RealTimeが大事)
優先度ごとのReadyキュー
基本FIFO型の切り替え
優先度継承(mutex)
優先度は1〜31(小さいほど高い)
(※デフォルト設定の場合)
最大値はユーザ定義。なるべく小さい値にした方が効率は良い。
優先度が固定のため、優先度の再計算が不要。
OSの管理する割込ハンドラよりも高優先のハンドラも可能。
-
NORTi(μITRON4)の場合
1tick=10msec(NORTi)
固定優先度(RealTimeが大事)
優先度ごとのReadyキュー
基本FIFO型の切り替え
優先度継承(mutex)
FIFO型のためクォンタムが不要。
Round Robin型にしたい場合は、タイマー割込などでReady Queueを回転させることで実現可能。
-
Linux 2.4の場合
1tick=10msec(通常)
固定優先度+動的優先度
一つのReady Queue
優先度と残りクォンタム、そして割当妥当なCPUなどから、次に相応しいタスクを探す
-
Linux 2.4の場合
1tick=10msec(通常)
固定優先度+動的優先度
一つのReady Queue
優先度と残りクォンタム、そして割当妥当なCPUなどから、次に相応しいタスクを探す
優先度は「基本クォンタム時間+残りクォンタム時間」
(基本クォンタム時間はデフォルト200msec)
SCHED_RR Round Robin型
SCHED_OTHER 応答型、時分割型(4.3BSDのように動く)
優先度は1〜99(大きいほど高い)
SCHED_FIFO 実時間型
-
Linux 2.4の場合
1tick=10msec(通常)
固定優先度+動的優先度
一つのReady Queue
優先度と残りクォンタム、そして割当妥当なCPUなどから、次に相応しいタスクを探す
1つのReady Queueから次に実行するに最も相応しい(goodness)タスクを線形検索する(複数CPUがあっても1つ)。
クォンタムを使い果たしたタスク :goodness = 0
リアルタイムタスク(1~99)の場合 :goodness = 1000 + 優先度
他 :goodness = 動的優先度
すべてのタスクのgoodnessが0になった時に、全クォンタムの補充を行う。
→毎秒やるよりは頻度が少ない
-
Linux 2.4の場合
1tick=10msec(通常)
固定優先度+動的優先度
一つのReady Queue
優先度と残りクォンタム、そして割当妥当なCPUなどから、次に相応しいタスクを探す
問題点
・スケーラビリティはあまりない
タスク数に応じて線形検索オーダが増加
タスク数が多くなった場合、I/Oバウンド型タスクの優先度が高止まりしてしまう
I/Oバウンド型が必ずしもユーザ対話型とは限らない(DB検索やネットワーク受信かもしれない)ため、本来のユーザ対話型のタスク応答性が悪くなる
・各CPU上で動作するスケジューラが同じデータを参照
・負荷の高いシステムではクォンタムが長過ぎる
・カーネルがNon-preemptiveである(ジャイアントロック)
-
Linux 2.6の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
Preemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
Preemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
-
Linux 2.6の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPU毎のReady Queue
KernelはCPUの数だけ
Active QueueとExpire Queue
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
Preemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
v2.6.13からはデフォルト値が4msecに変更
(ちなみにBeOSでは 3msec)
-
Linux 2.6の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPU毎のReady Queue
KernelはCPUの数だけ
Active QueueとExpire Queue
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
Preemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
SCHED_FIFO 実時間型
優先度は1〜139(小さいほど高い)
1〜99 固定優先度
100〜139 動的優先度
-
Linux 2.6の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPU毎のReady Queue
KernelはCPUの数だけ
Active QueueとExpire Queue
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
Preemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
SCHED_RR Round Robin型
SCHED_OTHER 応答型、時分割型(4.3BSDのように動く)
SCHED_BAT バッチ型(優先度があがらない)
変動は平均休止時間に依存する。
おおざっぱには、タスクが休止している間に経過した平均ナノ秒。
ただし、条件によって算出方法は異なる。
また、実行中は減っていく。この値は、タスクが対話型かどうかの
判断にも利用される。
SCHED_FIFO 実時間型
平均休止時間(msec)
ボーナス
-
Linux 2.6の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPU毎のReady Queue
KernelはCPUの数だけ
Active QueueとExpire Queue
静的優先度が高い(値が小さい)ほど、割当時間が多い
平均休止時間が長いほどBonus値が高くなり、Bonus値が高いほど動的優先度があがる
Bonus値が高いほど「対話型プロセス」として認識される。対話型プロセスはクォンタムの補充の可能性がある
-
Linux 2.6の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPU毎のReady Queue
KernelはCPUの数だけ
Active QueueとExpire Queue
O(1)スケジューラ
Task A
Task D
Task E
Task F
Active Queue
101
100
103
102
139
138
...
Task B
Task C
Expire Queue
101
100
103
102
139
138
...
CPU毎に用意されている
-
Linux 2.6の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPU毎のReady Queue
KernelはCPUの数だけ
Active QueueとExpire Queue
O(1)スケジューラ
Task A
Task D
Task E
Task F
Active Queue
101
100
103
102
139
138
...
Task B
Task C
Expire Queue
101
100
103
102
139
138
...
-
Linux 2.6.23の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
そこそこpreemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
CFS(Completely Fair Scheduler)
スケジューリングにヒューリスティックを使わない
優先度Queueを使わない
タスクQueueではなくタスクTree
-
Linux 2.6.23の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
そこそこpreemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
CFS(Completely Fair Scheduler)
スケジューリングにヒューリスティックを使わない
優先度Queueを使わない
タスクQueueではなくタスクTree
CPU上で実行可能なタスク数によって決まる一定の時間内に、確実にすべてのタスクがCPUを公平に共有できるようにする。
-
Linux 2.6.23の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
そこそこpreemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
CFS(Completely Fair Scheduler)
スケジューリングにヒューリスティックを使わない
優先度Queueを使わない
タスクQueueではなくタスクTree
ヒューリスティック(経験則)を使って対話型タスクを識別することはしない
-
Linux 2.6.23の場合
1tick=1msec(通常)
固定優先度+動的優先度
優先度ごと,CPUごとのReady Queue
そこそこpreemptiveなカーネル
KernelはCPUの数だけ
Active QueueとExpire Queue
CFS(Completely Fair Scheduler)
スケジューリングにヒューリスティックを使わない
優先度Queueを使わない
タスクQueueではなくタスクTree
各タスクの実行された時間と待たされた時間を元に各タスクをいつから実行するかを計算し、その時間をキートする赤黒木に格納する。
スケジューリングの際には赤黒木の一番左のタスクが選択され、他のタスクの時間が来るか待ちが発生するまで動く。
-
Xenのスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
bvt (borrowed virtual time)
sedf(Simple Early Deadline First)
credit
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
-
Xenのスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
bvt (borrowed virtual time)
sedf(Simple Early Deadline First)
credit
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
v3.0.2まで。現在は未サポート。
ドメイン毎に最小時間が決められていて、その間はドメインは割込まれずに実行することが保証される。
-
Xenのスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
bvt (borrowed virtual time)
sedf(Simple Early Deadline First)
credit
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
ドメイン毎に周期とクォンタムが割当てられ、この周期毎にクォンタム分だけCPUを使うことが可能。Deadlineが近いほど優先。Runnable QueueとWait Queueが実CPU毎にある。
bvtとsedfには、SMP環境でのスケーラビリティに欠ける。=CPU間で自動でロードバランスすることができない。
-
Xenのスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
bvt (borrowed virtual time)
sedf(Simple Early Deadline First)
credit
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
MB
CPU
CPU
Core
Core
Core
Core
HT
HT
現在のスケジューラ。
物理CPU毎にRun Queueを持ち、Run Queue間のロードバランスを行う。各ドメインにcreditという数が割当てられ、このcreditに比例してCPU時間を公平に割当てる。仮想CPUはcreditの残りがある状態のUNDERと、creditを使い切った状態OVERのいずれかになり、UNDERが優先して割当てられる。
creditは10msec毎に一定量ずつ減る。すべてのドメインのcreditが0になるとリセット。
weightパラメータによる重み付けも可能。
-
おまけ
-
I/Oスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
-
I/Oスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
ディスクアクセスを効率よく行うためのスケジューラ
要求通りの順にディスクアクセスを行うよりも、近いものをまとめたり、シーク順序を変えたりすると効率がいいんじゃないの?という話。
I/Oスケジューラはエレベータとも呼ばれ、ドライバに送るための発行Queueを持ち、そのQueueにどう積んでいくかで4つのタイプがある。
ちなみに、Linux2.6でのデフォルトは「予測エレベータ」。カーネル起動パラメータで変更が可能。
-
I/Oスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
No Operation
何もしない。要求のまま発行Queueに積む。
-
I/Oスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
Complete Fairness Queueing
プロセスIDからハッシュをとり64種類に分類する。
それをRound Robin型で一連の要求を発行する。
-
I/Oスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
Deadline
4つのQueueを使用。並べ替えQueueとDeadline Queueが読み/書きそれぞれある。並べ替えQueueにはセクタ順に要求が並んでいる。Deadline Queueにはリクエストからの期限順で並んでいる。
まず期限切れを確認。あればその要求とそれに物理的につながっている要求があれば、その一連を発行。期限切れがない場合、最後に発行した要求の次の要求から始まる一連を発行。並び替えQueueの最後までいったら再度先頭から検索。
読みと書きでは読みが優先(読みは通常、それを待っているタスクがいるため)。期限は読みが500msec、書きが5sec。読みが続きすぎてしまうときは、たまに書き。
-
I/Oスケジューラ
無処理エレベータ
完全公平型エレベータ
期限付きエレベータ
予測エレベータ
Anticipatory
期限付きエレベータの発展形。期限は読みが125msec、書きが250msec。
読みと書きの操作は交互。
順方向へのシーク距離に対して、逆方向へのシークが半分以下ですむ場合は、逆向きにシークさせることがある。プロセスからのI/O処理統計を収集し、同じプロセスから読み(書き)が続くと予想すれば7msec待つ。
-
Q & A
-
Fin.