こんにちは、ナナです。
OS機能が持つスケジューリングとは実行状態となるべきタスクを選び出すことを言います。
採用されるスケジューリング方式の違いにより、タスクの動き方は大きく変化します。
そのため、ITRONのシステムを開発する方は、ITRONがどのようなスケジューリング方式を採用しているかを知っていなければマルチタスクの動きを掴むことができません。
本記事では次の疑問点を解消する内容となっています。
では、スケジューリングの仕組みを学んでいきましょう。
スケジューリングを司るスケジューラとディスパッチャ
OSにはスケジューリングを実現するための機能が含まれており、その機能を「スケジューラ」と「ディスパッチャ」と呼びます。
この2つの機能は非常に仲が良く、お互いが連携しあうことでスケジューリングを実現します。
スケジューラの役割
スケジューラの定義をITRON仕様書で見てみましょう。
タスク状態の説明において「実行可能状態」と呼ばれる状態がありました。この状態にはシステム内で生成されたタスクが複数所属することができます。
スケジューラの役割とはこの「実行可能状態」のタスク達の中から、次に実行状態になるべきタスクを選出することです。
実行状態に選出する方式はOSによっていろいろありますが、それは後程解説しましょう。まずは、スケジューラ機能の役割を知っておいてください。
ディスパッチャの役割
続いてディスパッチャの定義を見てみましょう。
ディスパッチャの仕事は、スケジューラによって選出されたタスクを実行可能状態から実行状態に切り替えることです。
この図ってイメージではあるんですけど、実はリアルタイムOSの中では本当にこのような感じでタスク切り替えが行われています。
実行状態のタスクは1人しかなれないことに注意です。「TASK3」の動作が終わったら、また次のタスクが実行可能状態の中から選出され、動作の順番が回ってきます。
スケジューリング方式の種類
汎用OSも含めてスケジューリング方式にはいくつかの種類があります。各OSの特性に合わせてスケジューリング方式が選択され実装されています。
まずは代表的なスケジューリング方式を紹介しましょう。
FCFS方式(First Come First Served)
この方式は私たちの生活の中で基本となるスケジューリングです。
先に来た人が先にサービスを受けられる方式ですね。コンビニやスーパーなどのレジはまさしくこの方式です。
先に並んだタスクから先にサービスを受けられるというのは、まぁ平等といえば平等なのですが、場合によってはなかなかタスク処理が終わらず、後ろに並んだタスクが長く待たされるようなケースがあります。
ラウンドロビン方式
この方式は一定時間でタスクの動作を打ち切る方式です。打ち切られたタスクはまた最後尾に並びなおすことになります。
FCFS方式のように前のタスク処理が長引いても、タスクが切り替わるため長く待たされるということがなくなります。
しかし、逆に言えば重要な処理をしていたのに途中で打ち切られるといったこともあることに注意が必要になります。
優先度ベース方式
この方式はタスクというものに優先度という情報を付与することで、より優先度の高いタスクを優先的に動作させる方式です。
優先度というパラメータを適切に付与することができれば、重要度の高い処理から順に終わらすことが可能な方式です。
ITRONのスケジューリング方式とは
ITRONでは2つのスケジューリング方式を組み合わせたものが採用されています。
- 優先度ベース方式
- FCFS方式
まずは全体をタスク優先度というパラメータで大きく分類分けします。同一のタスク優先度が与えられたタスク同士ではFCFS方式で先に並んだ勝ちで実行順番を決定します。
①~⑥の数字は「優先順位」と呼ばれる数字です。優先順位は優先度とFCFSという2つの方式に則り決められたタスク切り替えの並び順を示します。
つまり、ITRONのスケジューラ機能は、この優先順位に従って「実行状態」となるべきタスクを選定するということになります。
ITRONにおけるこのスケジューリング方式のことを
プリエンプティブな優先度ベーススケジューリング方式
と呼んでいます。
「プリエンプティブ」とは横取り可能という意味である!
現在のタスクAよりも優先順位の高いタスクBが実行可能状態になった場合は、タスクAから実行する権利を取り上げ、タスクBに実行権を与える。
実行状態の実行権を横取りできる方式ということを「プリエンプティブ」という言葉で表現している!
ITRONのタスク優先度の扱い
ITRONのタスク優先度のパラメータは設計者である皆さんが決定する必要があります。
CRE_TSK時にタスク優先度を示すパラメータが存在しています。各タスク関数の後ろの1、2、2の値がタスク優先度になります。
CRE_TSK(TSKID_MAIN, {TA_HLNG|TA_ACT, 0, MAIN, 1, 128, NULL});
CRE_TSK(TSKID_TASK1, {TA_HLNG|TA_ACT, 0, TASK1, 2, 128, NULL});
CRE_TSK(TSKID_TASK2, {TA_HLNG|TA_ACT, 0, TASK2, 2, 128, NULL});
ITRONの優先度は数字が小さいほど優先度が高くなります。これはOSによって逆になることもあるため間違えないように注意しましょう。
タスク優先度の決め方
皆さんはタスクというものをシステムの中でいくつも作ることができます。ITRONでは各タスクに優先度というパラメータを決めて付与する必要があります。
ここで悩むのが「優先度をどのように決めればよいのか」ということです。
タスク優先度は対象となる2つのタスクの関係性にて決定します。タスク優先度は基本的には次の考えで決めるとよいでしょう。
- 緊急度のより高いタスクを優先度高にする
- 短いスパンで処理をするタスクを優先度高にする
困ったときは、2つのタスクに与えたミッションが仮に両方同じタイミングで発生したときに、「あなたならどちらを先に行う必要があるか」を自問自答することです。
複数のタスクがある場合は、それぞれの組み合わせでタスク優先度を決めていきます。
タスク優先度の差の扱い
2つのタスク優先度を決める際に優先度という数値の差の大きさは特に影響がありません。ITRONにおいて大事なのは2つのタスク優先度の大小関係のみです。
このように優先度の差が狭かろうが広がっていようが、タスクスケジューリングには影響はありません。それを踏まえた上でタスク優先度を決定するとよいでしょう。
HOSにおけるタスク優先度の範囲
HOSではタスク優先度の設定範囲を独自静的APIにて指定する形式をとっています。現状のsystem.cfgに次の指定がされているのを見てみましょう。
HOS_MAX_TPRI(8); // 最大優先度(省略時 16)
この値は皆さんが自由に変更できます。最大優先度がこの静的APIで範囲が決まっていることは頭の片隅に入れておくとよいでしょう。