タスク間通信の設計

RTOS(Real-Time Operating System:リアルタイムOS)はタスクの並行動作を前提とした構造になっており、柔軟な処理制御を実現しています。その一方で、タスク間でのデータ共有や整合性の保ち方、同期や通知の実現は設計上の課題になります。この記事では代表的な通信手段であるメッセージキューとイベントフラグに着目し、それぞれの役割と使い分けについて解説します。

RTOSでのタスク間通信設計

RTOSは、システムの処理を独立したタスクとして管理し、優先度や状態に応じて処理を進めます。

タスクは並行して動作しますが、タスク間で共有・更新するデータがある場合や、処理の実行順序の調整を要する場合は、タスク間で整合性を取る仕組みを考える必要があります。タスク間で実施されるデータやステータスのやり取りの方法を設計することがタスク間通信設計です。

メッセージキューの役割

メッセージキューは、タスク間でデータを受け渡すための代表的な手段です。送信側がキューにデータを書き込み、受信側が取り出すことで通信が成立します。容量の大きいデータはキューでポインタ(参照)を渡し、実体は共有バッファに置く設計が一般的です。この場合、共有バッファへのアクセスに対する排他制御とセットで検討します。参照渡しの場合は、バッファの所有権(生成および解放の責務)と、参照期間中の排他(または不変性)をあわせて定義します。

メッセージキューは非同期の受け渡し手段であり、キューに空きがある限り、送信側は受信側の処理タイミングとは独立してデータを投入できます。ただしキューが満杯の場合は、送信側が待ち(ブロック)に入る、タイムアウトする、または失敗するため、送信APIのブロック時間やエラーハンドリングを設計時に決めておく必要があります。

メッセージキューは、送信された順序でデータを管理するFIFO(First In, First Out)方式で動作することが基本です。ただし、RTOSによっては送信位置(先頭/末尾)を選べるものもあります。同じキューを待つ受信タスクが複数ある場合、どのタスクが起床して処理するかは、タスク優先度(同優先度の扱いはOS設定)に依存します。

イベントフラグの役割

イベントフラグは「状態(ビットが立っている/いない)」を表す用途に向いています。通知として使う場合は、(1)クリアしないと次回待ちが即時復帰して意図しない再実行が起きる、(2)クリアのタイミング次第でイベントを見逃す、などの問題が起き得るため、クリア条件(Clear on exitなど)を設計して取りこぼしや多重実行を防ぎます。すべての条件を満たした時点で実行する「AND条件」や、いずれかの条件を満たせば実行できる「OR条件」が代表的です。

イベントフラグの活用により、タスクの実行条件や実行順序を明確にできるほか、タスクごとの依存関係も簡潔に表現できます。

メッセージキューとイベントフラグの使い分け

メッセージキューはデータを渡す仕組みであり、イベントフラグは状態を通知する仕組みです。同じタスク間通信ではありますが、用途が異なるため、違いを理解して使い分ける必要があります。

たとえばイベントフラグはイベントのステータスなどを受け渡す仕組みのため、データそのものの受け渡しには向きません。反対にメッセージキューでフラグを受け渡すと、最新値だけわかればよい場合にも変更履歴まで流してしまうため、冗長になりやすいです。

複数のイベントの状態がそろうまで待ちたい場合には、イベントフラグの活用が適しています。

メッセージキューとイベントフラグの組み合わせ方

RTOSにおけるタスク間通信の組み合わせ例

メッセージキュー(データ転送) + イベントフラグ(状態通知)

RTOSにおけるタスク間通信の組み合わせ例

実際のシステム開発では、メッセージキューとイベントフラグを組み合わせて使うアプローチも有効です。たとえば、複数の異なる事象(複数のキューからの受信や、タイマ、ハードウェア割り込みなど)を1つのタスクで同時に待機したい場合に効果的です。

受信側はイベントフラグを待機条件として処理を止めておき、フラグが立ったタイミングでメッセージキューからデータを取り出す仕組みが実現できます。データがない場合も定期的に確認するポーリング(Polling)と比べて、無駄なCPU消費の削減に有効です。

このように役割を分離して使用することで、通信の効率化が狙えるだけでなく、設計の意図も明確になります。

設計時の注意点

開発時のデバッグや運用開始後の保守業務を考慮して、データの流れを追えるようにしておくことが重要です。メッセージキューはデータの流れが明確なため、問題が発生した箇所や原因となったデータをログから分析しやすい強みがあります。

一方、イベントフラグは処理の進捗によって値が随時書き換わるため、実行順序に依存する不具合を引き起こすおそれがあります。初期化の漏れや複数のタスクからの更新競合も考慮し、イベントフラグの状態を可視化できる設計にしておくことが、スムーズなデバッグには不可欠です。

また、タスク間通信では、各処理の役割を明確に分離しておくことも保守性の向上に効果的です。モジュール間の依存関係を減らすことで、メンテナンスのしやすいシステムを実現できます。

組み込みソフトの世界 トップへ戻る