本記事は、eForceの【開発者から学べる入門ウェビナー】RTOS基礎編をベースとしています。今回はRTOS(リアルタイムOS)の代表的な機能である [ 時間管理 ]、[ スケジューラーの仕組み ]、[ マルチタスク機構 ] について解説します。
前回は [ RTOSの動作の仕組み ] や、[ RTOS上でのアプリケーション作成の流れ ]、[ μITRON(マイクロアイトロン)の概要 ] について解説しました。
本記事でわかること
- 時間管理:システム時刻管理 / 周期処理の機能
・定周期処理
・タイミング制御 - スケジューラの仕組み
・優先度の高いタスクから実行
・最初に実行待ち状態に入ったタスクから実行(FCFS方式)
- マルチタスク機構
・タスク単位での機能分割
・各タスクの優先度設定
RTOS入門:スケジューラーの仕組みとマルチタスク機構
1.時間管理 カーネルタイマ
時間管理の代表的な機能
μITRONは、カーネルタイマを利用して時間を管理しており、次の代表的な機能が利用できます。
処理遅延(dly_xxx)
自タスクをシステムコールが呼び出された時刻から指定される時間の間、待ち状態に遷移させます。
周期起動 (cyc_xxx)
システムを構築する際に一定時間毎に何らかの処理をしたい時に利用します。
周期ハンドラは一定周期で起動されるタイムイベントハンドラです。
タイムアウト (txxx_xxx)
OSの機能を利用するためにシステムコールで呼び出しを実行後、指定時間が経過しても処理が実行されなかった場合にタイムアウトを行います。
アラーム (alm_xxx)
時間経過の監視に用います。タスクでアラームをセットし、指定時間内に次の呼び出しが行われない場合などに、RTOSが指定した関数を呼び出します。
システムコールとは実行中のプログラムがOSの機能を呼び出すために使用する仕組みのことです。また、その命令や関数などのAPIをさします。
xxx_yyy | XXXの部分が操作の種類を表す。YYYの部分が操作の対象(オブジェクト)を表す。 |
fxxx_yyy | 強制を示す。 |
ixxx_yyy | タスクコンテキスト以外から使用するシステムコール。μ3Cの場合は、iがつくシステムコールもつかない場合と同じ実装。 |
pxxx_yyy | ポーリング。待つ可能性がある場合はタイムアウトエラーでリターン。 |
txxx_yyy | 待ちに入る場合、指定された時間まで待つ。時間が経過しても処理が完了しなければタイムアウトエラーでリターン。 |
vxxx_yyy | インプリメント依存を示す。 |
2.マルチタスク機構
マルチタスク機構とは
カーネルが持つ主な機能の一つに、マルチタスク機構があります。マルチタスクとは、複数のタスクを並列に処理するためにCPUを仮想化、多重化するシステムのことですが、実際にはある時刻にCPUが実行できるのはひとつのタスクのみです。RTOSは、時分割で制御して複数のタスクの実行を疑似的に平行実行させる機構を持っています。
マルチタスク機構は、大きくわけて以下の2つで構成されています。
・スケジューリング ・コンテキスト切替 |
これよりスケジューリングを解説し、コンテスト切替は5章で解説します。
LEDの点滅処理で時間管理を考える
時間管理の実例としてLED点滅のサンプルを示します。Task Aは、実行状態、実行可能状態、待ち状態の三つの状態があり、LED点灯処理(実行状態)→dly_tsk(待ち状態)→イベント→実行可能状態→LED消灯(実行状態)→dly_tsk(待ち状態)→イベント…と繰り返すことによりLEDを点滅させています。
タスクの状態遷移とディスパッチ
eForce社のRTOS μC3/Compactにおいて、基本の状態遷移は4つの状態で表すことができます。
μC3の無償評価版はこちらから
▶︎ダウンロード
実行状態(RUNNING):現在タスクが実行中の状態
実行可能状態のタスクの中で最も優先順位の高いタスクの状態
実行可能状態(READY):実行可能になった状態
タスクを実行する条件は整っているが、当該タスクより優先度の高いタスク
または同一優先度で先に実行可能状態となったタスクが実行状態のため実行できない状態
待ち状態(WAITING):待ち解除の条件が満たされるのを待っている状態
条件が満たされると実行可能状態に遷移
休止状態(DORMANT):タスクが起動されるのを待っている状態
タスクの起動前、および タスク終了後の状態
LED点滅制御における具体的な遷移は以下の動画でわかりやすく解説しております。
▶︎【基礎編】RTOSとは?(19:40 – 24:00)
3.スケジューラーの仕組み
タスクの優先度とレディーキュー
実行可能状態における優先順位と優先度の関係図を示します。
タスクは休止状態から起動し、実行可能状態に遷移します。OSはタスクの状態を監視し、スケジューリングに従ってプロセッサが実行するタスクを切り替えるディスパッチが実行されます。ディスパッチが実行しない状態では、次のディスパッチが実行するまで保留されます。この間に、複数のタスクが実行可能状態になる場合を考えます。
実行可能状態に遷移したタスクはレディーキューに登録されます。レディーキューとは、実行可能状態にあるタスクのつながる行列を指します。全てのタスクには優先度が与えられており、複数の実行可能状態のタスクがある場合、最も高い優先度タスクからディスパッチにより実行状態に遷移します。
同一優先度のタスクが複数存在する場合は、先にレディーキューに並んだ順でタスクを実行します(FCFS方式)。また、スケジューラーの機能には、プリエンプト・ディスパッチがあります。これは、実行中のタスクを中断して、優先度の高い別のタスクに差し替えることを指します。例えば、もしタスクCが現在のタスクFよりも優先順位が高い場合、タスクFの実行権を取り上げ、タスクCに実行権を与えることができます。
タスクの優先度とレディーキューについては以下の動画でわかりやすく解説しております。
▶︎【基礎編】RTOSとは?(24:00-27:10)
RTOSの動作開始
RTOSなしの場合、CPUを起動させるブート処理や初期化を行った後に各処理を実行させますが、RTOSを動作させる際にはブート処理・初期化とタスク実行の間に中間の処理が必要となります。
具体的には上図のように、ユーザがメイン関数内にタスク処理からタスク起動までの一連の処理を作成する必要があります。ITRONでは、タスク生成情報などをコンフィグレーションと呼ぶ処理で実際のコードや変数として生成することが可能です。eForceの一部のパッケージ製品ではベースコードを自動で生成するコンフィグレータが付属しており、RTOS導入のサポートをします。
同期処理:優先度の設定も併用
同期処理とは、タスクの状態を直接的に操作してタスク間の同期を行う処理です。一例として、ゲームのコントローラのボタンが押された際にパンチをする動作を参考に考えてます。パンチをする動作のTask Bは通常wai_flgで待ち状態に設定されています。ボタンが押された際に割り込みサービスルーチンが起動し、イベントフラグ(i)set_flgで待ち状態が解除されます。Task Bの優先度が高いため即時実行状態になり、パンチを実行します。
4.イベントフラグの動作紹介
条件待ち合わせ
マルチタスク処理では、各タスクは必要なイベントが発生するまで待ち状態となります。そのため、イベントが発生した時に待ち状態を解除する動作が必要となります。イベントフラグとは、イベント(事象)をフラグの有無(ビットのON/OFF)という組み合わせで表現し、タスク間やタスクと割込みサービスルーチン間で通知するための機能です。
上記の画像のように各タスクに機能を割り当てた場合を考えます。コントローラを操作すると、割り込み処理が発生し、その操作に応じてイベントフラグが通知されます。赤いボタンが1ビットめ、黄色のボタンが2ビットめと予め定義し、受け取り側では対応するビットがONになるのを待ちます。これにより複数ボタンに応じた処理を構築でき、上図だと最大32種類のイベントを割り当てることができます。
優先度ベースのRTOSならではのメリット
上図は、タスクの状態遷移を時系列で示したものです。dly_tskなどのシステムコールを使って待ち状態にすると、タスクの切り替えが起こります。タスクの優先度は1が最も高く、数が多いほど優先度が下がります。図のように、低い優先度のTaskCは、TaskAとTaskBが待ち状態となることで初めて実行状態になります。また、先ほどのパンチの例では、コントローラが押されたときにiset_flgが呼び出され、TaskBが実行されてパンチをします。
イベントフラグの動作について以下の動画でわかりやすく解説しております。
▶︎【基礎編】RTOSとは?(28:45-34:20)
タスクスケジューリングの詳細例
イベントが発生してシステムコールを使うと、タスクの切り替わりが発生します。
Task Aが待ち状態になった後のTask BとTaskCの動きを時系列で見ることができます。Task Bがイベントフラグによって待ち状態が解除される場合のタスク遷移を、5つのステップで説明します。
(1) | (2) | (3) | (4) | (5) | |
TaskB 優先度1 |
B1 待ち状態 |
B2 待ち解除 |
B3 実行可能状態 |
B4 ディスパッチ |
B5 実行状態 |
TaskC 優先度2 |
C1 実行状態 |
C2 実行状態 |
C3 実行状態 |
C4 プリエンプト |
C5 実行可能状態 |
(1) Task Bが待ち状態、Task Cが実行状態です。
(2) イベントフラグの待ち解除によって Task Cが実行可能状態に遷移します。
(3) Task Bが実行可能状態となります。ここでは Task B3(実行可能状態)> Task C3(実行状態)と優先度の不均衡がおこります。
(4) (3)で優先度の不均衡が発生したことから、スケジューラーによってTask Bを実行可能状態から実行状態にディスパッチし、Task Cを実行状態から実行可能状態にプリエンプトします。
(5) Task C5(実行可能状態)< Task B5(実行状態)となり優先度が均衡となります。これでTask BとTask Cの状態遷移が行われています。
詳細な動きは以下の動画でわかりやすく解説しております。
▶︎【基礎編】RTOSとは?(35:20-38:0)
RTOS動作(タスクスケジューリング)のまとめ
ポイント
- タスク優先度は1が最高で、数が大きいほど低くなる
参考例(μC3/Compact:1~16)(μC3/Standard:1~31)
※ eForce製品での設定範囲 - システムコールを呼ばなければ低優先度のタスクに状態が遷移しなくなる可能性がある
- プリエンプト・ディスパッチにより、RTOSがタスク切替を実施
- タスク間協調:複数のタスクが連携してシステムを構築
μC3の無償評価版はこちらから
▶︎ダウンロード
5.コンテキスト切替
コンテキストの切替・概要
RTOSではイベントによってタスクの切り替え(ディスパッチ)が起こることがあります。タスク内に記述されたアプリケーションはタスク切り替えを意識せずに作成されてます。
図はタスクの切り替わりの例を示しています。現在実行中のTask Aは状態を保存し、待ち状態などに遷移します。かわりに実行状態になるTask Bでは前回待ち状態となった時の状態に復帰し、ディスパッチなどが実行されます。
RTOSでのプログラム実行環境はコンテキストと呼ばれ、タスクやタイムイベントハンドラ、割り込みハンドラごとにそれぞれ持ちます。コンテキストを切り替える場合、CPUのプログラムカウンタ(PC)、スタックポインタ(SP)、汎用レジスタ(REG)など必要なレジスタ情報などをスタック空間に保存する必要があり、再開時に保存した情報を復元し実行を再開します。
スタック領域を準備する
コンテキストの切り替えにはスタック領域という、実行中のタスクの状態をすべて保存するための専用のメモリ領域が必要となります。スタック領域はアプリ作成時に定義する必要があり、タスクで使用する変数とレジスタを保管するための十分な容量を持っている必要があります。
スタック領域の定義が不足し、実際の使用量を上回ることをスタックオーバーフローと呼びます。スタックオーバーフローはシステム全体にとって致命的なエラーとなり、原因究明も困難となるため、ユーザは必要なスタック領域を見積もり、適切に指定する必要があります。
タスク間協調処理
RTOSでは各機能ごとにタスクを実装し、優先度が割り当てられます。複数タスクを並行処理する場合、タスク間で連携動作させたり、タスク間での情報交換をするタスク間の協調が必要となります。
本記事では、タスク間の協調の例としてイベントフラグに焦点を当てました。μITRONで定義されいる他の機能についても下図に示します。
種類 | 特徴 | μITRONによる手段(例) |
排他 | 資源待ち合わせ | セマフォ、(ミューテックス)など |
同期 | 条件待ち合わせ | イベントフラグ |
通信 | タスク間でのデータ交換 | データキュー、メールボックス(メッセージバッファ) |
動画資料をご覧になりたい方へ
動画資料をご覧になりたい方はこちらからダウンロード可能です。