変更要約: 初版
3.3タスク間同期・通信
排他制御のためのセマフォとミューテックスの用途の違い(カウンティング資源管理 vs 排他所有権)、イベント発生を伝えるイベントフラグ、データの受け渡しに使うメールボックスとメッセージキューの違いを、実際のタスク間連携の設計場面でどれを選ぶべきかという判断とともに学びます。
複数のタスクが同じ資源を共有したり、互いに情報をやり取りしたりする組込みシステムでは、どの同期・通信手段を使うかの選択がバグの有無を左右します。「排他制御ならとりあえずセマフォ」といった雑な選択は、後述する優先度逆転などの重大な不具合につながりかねません。この節では各手段の本来の用途を正確に区別し、実務での選び方を学びます。
3.3.1セマフォとミューテックスの違い
- セマフォ(カウンティングセマフォ)=資源の残数を数えるカウンタとして動作する同期プリミティブ。
take(P操作)でカウンタを減らし0未満なら待ち、give(V操作)でカウンタを増やす。同数までの複数タスクが同時に資源を使ってよい場合(例:3台あるバッファプールの空き管理)や、割込みハンドラから起床のシグナルを送る用途に向く。カウンタが1のみの二値セマフォは単純な排他にも使えるが所有権の概念がない。 - ミューテックス(Mutual Exclusion)=「誰が資源を占有しているか」という所有権を持つ排他制御専用の同期プリミティブ。取得したタスクだけが解放できる(取得者と解放者が同一でなければならない)という制約があり、この所有権情報があるからこそ、後述の優先度継承(priority inheritance)プロトコルを実装できる。単なるカウンタであるセマフォには所有権が無いため優先度継承を組み込めない。
- 実務上の選択:「排他制御(1タスクだけが資源を使う)」ならミューテックス、「資源の個数管理や割込みからの起床通知」ならセマフォが原則。優先度逆転対策が必要な排他制御に二値セマフォを流用するのは典型的な設計ミス。
3.3.2イベントフラグとメールボックス・メッセージキュー
- イベントフラグ=複数のビットで複数の事象の発生・未発生を表現する同期手段。1つのタスクが「複数の条件のAND(全部そろった)またはOR(どれか1つ)が成立したら起床する」という待ち方ができ、複数のセマフォを個別に待つより効率的に複合条件を表現できる。
- メールボックス=1個のメッセージ(多くは1ポインタ分)だけを保持できる、単純な1件限りのデータ受け渡し手段。次のメッセージが来る前に前のメッセージを読み出す必要がある実装が多い。
- メッセージキュー=複数個のメッセージをFIFOで貯められるバッファを持つデータ受け渡し手段。送信側と受信側の処理速度にばらつき(バーストするデータ)がある場合に、キューがバッファとして緩衝材になり、取りこぼしを防ぐ。容量(キュー長)の設計判断が重要。
「ミューテックスは所有権を持ち取得者しか解放できない(優先度継承の実装に必須)」「セマフォは資源数のカウンタで割込みからの起床通知にも使う」「メールボックスは1メッセージのみ、メッセージキューは複数メッセージをFIFOで保持」が最頻出です。排他制御にセマフォを使うと優先度継承を組み込めないという点は優先度逆転の節(次節)と合わせて狙われやすい急所です。
あるファームウェア開発者が、センサデータを共有バッファに書き込むタスクAと、そのバッファを読み出して処理するタスクBを設計しているとします。まず「共有バッファへの同時アクセスを防ぐ」という要件に対しては、ミューテックスを選ぶべきです。理由は、後にこのバッファアクセスの優先度逆転対策として優先度継承プロトコルを組み込みたくなった場合、ミューテックスなら「今誰が占有しているか」という所有権情報がRTOSカーネルに保持されているためプロトコルを適用できますが、二値セマフォでは所有権の概念がなく後から継承を組み込めないためです。次に「センサ割込みが発生したらタスクAを起床させる」という要件には、セマフォ(多くはISRからgiveできるバイナリセマフォ)を使います。割込みハンドラは所有権を持つ概念にそぐわないため、ここはセマフォが適切です。さらに、「タスクAが読み取ったセンサ値をタスクBへ渡す」通信については、センサがバースト的に複数の値を短時間で生成する可能性があるなら、1件しか保持できないメールボックスでは前の値が上書きされる(またはタスクBが読み出すまでタスクAがブロックされる)ため、複数個をFIFOで蓄えられるメッセージキューを選び、キュー長をバーストの最大件数に合わせて設計します。逆にセンサ値が常に1件ずつ確定的なタイミングで生成されるなら、シンプルなメールボックスで十分です。「排他はミューテックス、割込み起床はセマフォ、バーストするデータの受け渡しはメッセージキュー、単発の受け渡しはメールボックス」という使い分けの原則を状況ごとに適用することが、組込み設計者に求められる判断です。
| プリミティブ | 本来の用途 | 所有権の有無 |
|---|---|---|
| ミューテックス | 排他制御(1タスクのみが資源を占有) | あり(優先度継承の実装に必須) |
| セマフォ | 資源数の管理・割込みからの起床通知 | なし |
| イベントフラグ | 複数条件のAND/OR待ち合わせ | なし |
| メールボックス | 1件のみのデータ受け渡し | なし |
| メッセージキュー | 複数件のFIFOバッファ付きデータ受け渡し | なし |
ひっかけ: 「排他制御にはセマフォとミューテックスのどちらを使っても本質的に同じである」は誤りです——ミューテックスは所有権を持つため優先度継承を実装できるが、セマフォは所有権が無くこの対策を組み込めないため、優先度逆転が問題になりうる排他制御には原則ミューテックスを使うべきです。また「メールボックスとメッセージキューは同じものである」も誤り=メールボックスは1件のみ保持、メッセージキューは複数件をFIFOで保持する点が異なります。
3.3.3この節のまとめ
- ミューテックスは所有権を持つ排他制御専用、セマフォは資源数カウンタ・割込み起床通知に使う
- 所有権が無いセマフォでは優先度継承を実装できず、優先度逆転対策が必要な排他にはミューテックスを選ぶ
- メールボックスは1件のみ、メッセージキューは複数件をFIFOで保持しバーストするデータの緩衝材になる
進捗の記録にはログインが必要です。
理解度チェック
(軽い確認用)Q1. 共有バッファへの排他アクセスに二値セマフォを使っていたが、後から優先度逆転対策として優先度継承を組み込みたくなった。この時点で判明する設計上の問題として最も適切なものはどれか。
Q2. センサが短時間に複数の値をバースト的に生成し、処理タスク側の読み出し速度がそれより遅い場合がある。センサ読み取りタスクから処理タスクへ値を受け渡す手段として最も適切なものはどれか。
Q3. あるタスクが「センサ初期化完了」と「通信リンク確立」の両方のイベントが成立して初めて起床すべきという要件がある。この要件を最も自然に実現できる同期手段はどれか。

