Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Linuxのプロセススケジューラの歴史 v0.01~v2.4.x

Linuxのプロセススケジューラの歴史 v0.01~v2.4.x

以下動画のテキストです。
https://youtu.be/iPlcotf6It4

842515eaf8fbb2dfcc75197e7797dc15?s=128

Satoru Takeuchi
PRO

January 29, 2022
Tweet

More Decks by Satoru Takeuchi

Other Decks in Technology

Transcript

  1. Linuxのプロセススケジューラの歴史 v0.01~v2.4.x Jan. 29th, 2022 Satoru Takeuchi Twitter: satoru_takeuchi 1

  2. はじめに • Linuxカーネル(以下カーネル)のプロセススケジューラの歴史を振り返る • 対象バージョン: 最初のリリースv0.01からv2.4.xまで • 用語 ◦ タスク:

    カーネルのスケジューリング単位。プロセスあるいはスレッド ◦ LCPU: カーネルがCPUとして認識するもの(物理CPU or コア or スレッド) ◦ Current: LCPU上で現在動作中のタスク 2
  3. V0.01: 概要 • 超絶シンプルなラウンドロビンスケジューリング ◦ コア部分は20行弱 • タスクを管理する配列がそのままランキュー ◦ 長さは64:

    つまりタスクは最大でも 64 ◦ 空要素にはnilが入る • タイムスライスは固定150[ms] ◦ インターバルタイマーの 1tickは10[ms] ◦ のちにタイムスライスはコロコロ変わるが、あまり重要じゃないので省略 • currentのタイムスライス切れ or 全タスクがsleepならスケジューラを呼ぶ 3
  4. V0.01: スケジューリングアルゴリズム • ランキューを全走査して残りタイムスライスが最大のものを次に動かす • 該当者がいなければ全タスクのタイムスライスをリセット ◦ タイムスライスが切れているプロセスには 150[ms]与える ◦

    スリープ中のタスクには残りタイムスライス /2をボーナスとして与える ▪ 寝起きを繰り返すbashなどを起床時に優先的に動作させる仕組み (多分) 4
  5. スケジューラの挙動: 初期状態 5 runnable 10 runnable 15 nil runnable 5

    ランキュー (タスク管理配列) sleep 12 タイムスライス タスク未割当 タスクの状態 t0 t1 t2 t3 t4
  6. スケジューリング 6 runnable 10 runnable 15 nil runnable 5 ランキュー

    (タスク管理配列) sleep 12 ランキュー全走査 runnableの中でタイムスライスが最大のものを選ぶ t0 t1 t2 t3 t4
  7. t1がタイムスライス切れ 7 runnable 10 runnable 0 nil runnable 5 ランキュー

    (タスク管理配列) sleep 12 t0 t1 t2 t3 t4
  8. 次のスケジューリング 8 runnable 10 runnable 0 nil runnable 5 ランキュー

    (タスク管理配列) sleep 12 ランキュー全走査 runnableの中でタイムスライスが最大のものを選ぶ • タイムスライスが同じタスクが複数いれば最初に見つかったものを選択 t0 t1 t2 t3 t4
  9. 全員がタイムスライス切れ or sleep 9 runnable 0 runnable 0 nil runnable

    0 ランキュー (タスク管理配列) sleep 12 t0 t1 t2 t3 t4
  10. タイムスライスをリチャージ 10 runnable 15 runnable 15 nil runnable 15 ランキュー

    (タスク管理配列) sleep 21 • スリープ中のタスクには残り ”タイムスライス/2”をボーナスとして与える t0 t1 t2 t3 t4
  11. sleepから起床したタスクはrunnableになるだけ 11 runnable 15 runnable 15 nil runnable 15 ランキュー

    (タスク管理配列) runnable 21 t0 t1 t2 t3 t4 おはよう • Preemption? そんなものは無い
  12. V0.01: その他 • Nice値 ◦ 変更するとタイムスライスが増減 ◦ rootでなくてもマイナス値を設定可能 ◦ 任意の値を設定可能

    ▪ 例: nice値-10,000 => タイムスライスは100,150[ms] ◦ 絶対値を指定できない : setpriority()システムコールは無い • タスク == プロセス。カーネル内でスレッドを扱えない 12
  13. v1.0 • Preemptionの導入 ◦ 条件: sleepから起床したタスクのタイムスライス > currentのタイムスライス • Nice値の扱いがまともになる

    ◦ Rootでないとマイナス値を設定できなくなる ◦ nice値は-19~20の間のみ意味を持つようになる ◦ Nice値の絶対値を指定可能に : {set,get}priority()システムコールが追加 13
  14. v2.0 • ランキューのデータ構造がリストに • SMP対応 • リアルタイムポリシーの追加 14

  15. ランキューデータ構造がリストに • スケジューリングアルゴリズム ◦ ランキューからタイムスライスが最大のタスクをとってくる • タイムスライスを使い果たすとランキュー末尾に挿入 • 生成直後&sleep起床時のタスクもランキュー末尾に挿入 •

    ランキューへのタスク挿入時にソートしない ◦ スケジューリング処理の計算量は O(n): nはrunnableタスクの数 15
  16. スケジューラの挙動: 初期状態 16 Runnable 10 Runnable 15 Runnable 5 t0

    t1 t2
  17. スケジューリング 17 Runnable 10 Runnable 15 Runnable 5 ランキュー全走査 runnableの中でタイムスライスが最大のものを選ぶ

    t0 t1 t2
  18. タイムスライス切れ 18 Runnable 10 Runnable 0 Runnable 5 t0 t1

    t2
  19. タイムスライス切れタスクはランキュー末尾へ 19 Runnable 10 Runnable 5 Runnable 0 • この後の流れはv1.0以前のものと同じ

    t0 t2 t1
  20. sleepから起床したタスクはランキュー末尾へ 20 Runnable 10 Runnable 5 Runnable 0 Runnable 15

    t0 t2 t1 t3 おはよう • Preemption発生 ◦ T3のタイムスライス > current(t0)のタイムスライス
  21. V2.0: SMP対応 • ランキューはグローバルなもの1本 • sleepからの起床時には直前に動作したLCPU上で動作しやすくなっている ◦ 前回動作時の状態がキャッシュメモリに残ってる可能性が高いという推測 (多分) •

    ロードバランサは無い(必要もない) 21 LCPU0 LCPU1 Runnable 10 Runnable 15 Runnable 5 共有 t0 t1 t2
  22. リアルタイムポリシーの追加 • タスクをリアルタイムタスクにできる ◦ 通常のタスク(SCHED_OTHERポリシー)より常に優先的に動作可能 ◦ 用途: ハートビート処理など (1秒ごとに起動して通信してすぐ寝る、など )

    • 二種類ある ◦ SCHED_FIFOポリシー: タイムスライスなし。ここではこちらのみ扱う ◦ SCHED_RRポリシー: タイムスライスあり • sched_setscheduler()システムコールやchrtコマンドによって設定 ◦ rootのみ設定可能 22
  23. スケジューラの挙動: 初期状態 23 Runnable OTHER 10 Runnable FIFO -- Runnable

    FIFO -- t0 t1 t2
  24. スケジューリング 24 Runnable OTHER 10 Runnable FIFO -- Runnable FIFO

    -- • ランキュー全走査 • リアルタイムタスクは「常に」通常のタスクより優先動作 t0 t1 t2
  25. リアルタイムタスクがcurrentになると… 25 Runnable OTHER 10 Runnable FIFO -- Runnable FIFO

    -- sleepするかexitするまでSCHED_OTHERがいくら待とうがずっと動作 t0 t1 t2
  26. v2.2とv2.4 • 大して変化なし ◦ タイムスライスの計算方法が変わったくらい 26

  27. まとめ • 初期におけるLinuxのプロセススケジューラの実装は極めてシンプルだった • 徐々に機能が増えてきた ◦ プリエンプション ◦ リアルタイムスケジューリング ◦

    SMP対応 27