【問題1】タスク間の同期と通信:“組み込み力”向上! ETEC対策ドリル Step2(1)
技術要素だけでなく、開発・管理技術まで範囲を広げ帰ってきたETEC対策ドリル! 今回はタスク間の同期・通信について
本連載の目的はETECのクラス2試験を対象に、演習問題を解きながら基礎知識を学ぶことです。
前作「“組み込み力”向上! ETEC対策ドリル」では、ETECクラス2の出題範囲の「技術要素」に該当する知識について解説しましたが、今回の新連載では、技術要素だけでなく、「開発技術」「管理技術」にまで範囲を広げていきます!
記念すべき連載第1回では、「タスク間の同期・通信」について説明します。早速ですが、問題を解いてみましょう。
今回の演習―【問題1】
【問題1】の補足
【問題1】は、タスク間の同期や通信に用いるオブジェクトに関する問題です。組み込みソフトウェアでは、複数のタスクを動作させますが、別のタスクの完了を待機したり、別のタスクから処理結果を受け取ったりしてから処理を行う場合があります。そのような場合には、「イベントフラグ」や「メッセージバッファ」などのオブジェクトを利用します。
ウ以外の記述には、誤りがあります。
アは、「タスク間通信を行う」が誤りです。「セマフォ」は、タスク間の同期や排他制御に用います。イは、「任意サイズのデータ領域を指すポインタをやりとりして」が誤りです。「メッセージバッファ」は、カーネルが管理するメモリ領域にデータをコピーして、タスク間通信を行います。エは、「カーネルが管理するメモリ領域にデータをコピーして、タスク間で同期を取る」が誤りです。「メールボックス」は、任意サイズのメッセージ領域を指すポインタをやりとりすることで、タスク間通信を可能にします。
それでは、タスク間の同期や通信の基本について解説していきます。この機会にしっかりと理解しておきましょう。
イベントフラグによるタスク間の同期
前作では、タスクの状態遷移や優先度について解説しました。
ソフトウェアの機能は、優先度を基に複数のタスクを切り替えながら実行していくことで実現します。このとき、それぞれのタスクは必ずしも独立して処理を実行するわけではなく、相互に依存する場合があります。例えば、あるタスクが処理の途中でスイッチなどの外部からの入力を必要とするときには、一度処理を中断し、入力処理を行う別のタスクが完了するまで待たなければなりません。このようにタスクの実行のタイミングを調整することを、「タスクの同期」といいます。
タスク間の同期には、セマフォやイベントフラグなどのオブジェクトを利用します。セマフォは、メモリやポートなどの共有資源について獲得と返却の操作を行うことでタスク間の同期を可能にするオブジェクトです。資源使用について競合を防ぐための排他制御に用いることが多いため、詳細については次回説明します。
イベントフラグは、タスクの終了や割り込みなどの「イベント(事象)」を条件として、タスク間の同期を制御する際に利用します。1ビットが1つのイベントを表すフラグを用い、イベントが発生したときには該当ビットを設定します。
例えば、タスクAがタスクBの処理完了を待つ場合、「タスクBの処理完了」のイベントを表すビットを指定してイベントフラグ待ちのシステムコールを呼び出し、待ち状態に遷移します。タスクBは処理が完了したら、タスクBの処理完了のイベントを表すビットを1に設定して終了します。すると、カーネルは待ち状態にあったタスクAを実行可能状態に遷移させるため、タスクAは(最も優先度が高ければ)実行状態に遷移して処理を続行できます。
図1 イベントフラグによるタスク間通信
(1)タスクAは、「タスクBの処理完了」を待つことを指定して、イベントフラグ待ちのシステムコールを呼び出し、待ち状態に遷移する
(2)タスクBは、イベントフラグ設定のシステムコールを呼び出して、処理の完了を通知する
(3)タスクAの待ち条件が満たされたため、タスクAはカーネルによって待ち状態を解除され、実行可能状態に遷移する
イベントフラグを利用する場合は、複数の条件を指定して、そのすべてが満たされるまで待機するか(AND待ち)、条件の一部が満たされるまで待機するか(OR待ち)を指定できます。
メッセージバッファやメールボックスによるタスク間の通信
タスク間の通信とは文字通り、タスク間でデータを送受信することです。メッセージバッファやメールボックスなどのオブジェクトを利用します。
メッセージバッファは、カーネルが管理するメッセージバッファ領域を介してデータをやりとりします。例えば、タスクAがタスクBに送りたいデータを指定して送信のシステムコールを呼び出すと、そのデータがメッセージバッファにコピーされます。タスクBは、受信のシステムコールを呼び出すと、メッセージバッファからこのデータを取り出すことができます。メッセージバッファにデータがない場合には、タスクBは待ち状態に遷移します。
一方、メールボックスは、データそのものではなく、データを指すポインタをやりとりします。例えば、タスクAはタスクBに送りたいデータをメモリ上の領域にコピーし、その領域のポインタを指定して送信のシステムコールを呼び出します。タスクBは、受信のシステムコールを呼び出すことで、メールボックスにコピーされたポインタを取り出し、メモリ上のデータを参照できます。メールボックスにポインタがないとき、タスクBは待ち状態に遷移するか、ポインタがないことを確認した後にシステムコールを終了して処理を継続します(呼び出したシステムコールによって異なる)。
メッセージバッファは、データそのものをコピーするため、データのサイズが大きいと処理の負荷が大きくなります。また、送信するデータがメッセージバッファに収まらない場合、メッセージバッファの領域が空くまで送信側のタスクが待ち状態に遷移してしまいます。
メールボックスは、ポインタのみをやりとりするため、処理の負荷が小さく、送信側のタスクが待ち状態に遷移することはありません。ただし、送信側と受信側のタスクがポインタを利用してメモリ上の同じ領域を参照することになるため、注意が必要です。また、データを格納する領域としてメモリを確保した際には、使い終わったときにメモリを忘れずに解放しなければなりません。
なお、メッセージバッファやメールボックスを用いてタスク間でデータをやりとりすることで、タスク間の同期を取ることも可能です。
課題演習―【問題2】
いかがでしたでしょうか? タスク間の同期と通信について理解できましたか。次回は、複数のタスクで資源を共有する場合に必要な「排他制御」と「デッドロック」について解説します。お楽しみに! (次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.