応用情報技術者 2012年 春期 午後 問07
オーディオプレーヤの組込みソフトウェアの設計に関する次の記述を読んで、設問1〜3に答えよ。
G社では、ハードディスクを内蔵した携帯型のオーディオプレーヤ(以下、プレーヤという)の組込みソフトウェアを開発することとなった。
プレーヤの本体には再生ボタン及び停止ボタンがある。再生ボタンを押すと、あらかじめハードディスクに圧縮して保存しておいた音声ファイルから、音声データを読み出して再生する。停止ボタンを押すと、音声ファイルの再生を停止する。
開発する組込みソフトウェアは、メインタスク、再生処理タスク、データ読み出しタスク及びDSP(Digital Signal Processor)ドライバから成る。タスク間の通信にはメッセージを使用する。プレーヤの構成を図1に示す。
開発する組込みソフトウェアでは、再生中に音声が途切れるのを防ぐために、バッファメモリを使用する。音声ファイルを再生する際には、データ読み出しタスクが音声データをバッファメモリに書き込む。再生処理タスクは、書き込まれた音声データを順次読み出し、DSPドライバに転送する。DSPドライバは圧縮されている音声データをDSPに供給して伸張する。伸張された音声データはスピーカに出力される。

〔バッファメモリの制御〕
バッファメモリの領域は、0〜n−1のn個に等分割し、その一つ一つをメモリブロックとして取り扱う。バッファメモリへの書込み及びDSPドライバへの転送は、メモリブロック単位で行う。
バッファメモリの制御の様子を図2に示す。pは、再生処理タスクが次に読み出してDSPドライバに転送するメモリブロックの番号である。pからm個のメモリブロックは使用中、それ以外のメモリブロックは未使用である。
データ読出しタスクの書込みと再生処理タスクの読出しのいずれも、メモリブロックの番号が0のメモリブロックから順に使用する。データ読出しタスクの書込み先のメモリブロックの番号がn-1に達したら、次はメモリブロックの番号が0のメモリブロックを使用する。また、再生処理タスクが読み出すメモリブロックの番号も、n-1に達したら、次はメモリブロックの番号が0のメモリブロックを使用する。

〔ハードディスクの制御〕
電力消費を抑えるために、ハードディスクは読出し処理で必要なときだけディスクを回転させ、読出しが終わったら回転を停止させる。ハードディスクの制御に用いる関数を表1に示す。

〔DSPドライバの制御〕
DSPドライバは、DSPを駆動する他、状況に応じて再生処理タスクにメッセージを送信する。DSPドライバの制御に用いる関数を表2に示す。
〔組込みソフトウェアのタスク構成〕
開発する組込みソフトウェアのタスクの動作内容を表3に示す。各タスクには実行状態、待ち状態及び停止状態があり、実行権はラウンドロビン方式で与えられる。
再生処理タスクの流れ図を図3に、データ読出しタスクの流れ図を図4に、図3及び図4で使用しているサブルーチン Buffering(s, t) の流れ図を図5に示す。
なお、図3中の下線①の判定条件は、音声データの追加読出しを開始する条件である。また、図4中の mod は剰余の演算子で、a mod b は a を b で割った余りである。


設問1:
表3中のa、bに入れる適切な字句を答えよ。
模範解答
a:再生処理
b:STOPメッセージ
解説
解答の論理構成
- 停止時にメインタスクが操作する相手
表3のメインタスク説明には
「再生ボタンが押され、音声ファイルの再生を開始するときには、再生処理タスクを立ち上げる。」
とあり、再生の開始・終了を直接担当しているタスクが “再生処理タスク” であることが読み取れます。したがって a には「再生処理」が入ります。 - メインタスクが送るべきメッセージ種別
停止を指示するのに用意されている標準メッセージは、表2で定義されている
「STOP:音声データの終端に到達したことを示す。」
です。再生を強制的に止める場面でも同じ “STOP” を使えば、再生処理タスクの分岐(STOP受信時に dsp_end() 実行)をそのまま活用できます。したがって b には「STOPメッセージ」が入ります。 - 以上より
a:再生処理
b:STOPメッセージ
誤りやすいポイント
- 「データ読出しタスク」と混同する
停止させたい対象は再生を実際に制御する “再生処理タスク” です。ハードディスクからの読み出しを行うタスクに STOP を送っても DSP は止まりません。 - READY と STOP を取り違える
READY は「次のメモリブロック処理準備完了」の通知であり、再生続行を意味します。「停止」にはふさわしくありません。 - タスク名の一部を省略する
解答は「再生処理タスク」ではなく、設問内空欄 a の位置に合わせた「再生処理」という字句が正解です。
FAQ
Q: STOPメッセージは DSP ドライバ専用ではないのですか?
A: 表2の説明に「DSPドライバは、再生処理タスクに…STOP…を送信する」とあり、送受信相手は“再生処理タスク”です。メインタスクが同じメッセージ種別を送っても問題なく解釈されます。
A: 表2の説明に「DSPドライバは、再生処理タスクに…STOP…を送信する」とあり、送受信相手は“再生処理タスク”です。メインタスクが同じメッセージ種別を送っても問題なく解釈されます。
Q: メインタスクが直接 dsp_end() を呼ばないのはなぜ?
A: 再生処理タスク内部で STOP 受信後に dsp_end() と後処理(バッファ残処理・タスク同期など)を一元的に実行する設計だからです。
A: 再生処理タスク内部で STOP 受信後に dsp_end() と後処理(バッファ残処理・タスク同期など)を一元的に実行する設計だからです。
Q: 再生ボタン連打による多重起動はどう防ぐ?
A: メインタスク側で再生処理タスクの状態を管理し、実行中は新規起動を許可しないフラグを持たせる実装が一般的です。
A: メインタスク側で再生処理タスクの状態を管理し、実行中は新規起動を許可しないフラグを持たせる実装が一般的です。
関連キーワード: タスク間通信, メッセージ駆動, 組込みOS, ラウンドロビン, バッファリング
設問2:
次にDSPドライバに転送するメモリブロックの番号がp、使用中のメモリブロック数がm個のとき、図4中のd、eに入れる適切な式を答えよ。
模範解答
d:p+m
e:n−m
解説
解答の論理構成
-
使用中領域の定義
【問題文】では「pは、再生処理タスクが次に読み出してDSPドライバに転送するメモリブロックの番号である。pからm個のメモリブロックは使用中、それ以外のメモリブロックは未使用である。」と規定しています。従って使用中ブロックはp, p+1, … , p+m−1です。 -
Buffering の目的
データ読出しタスクは「サブルーチン Buffering(s, t) を呼び出して、全ての未使用のメモリブロックを使って、ハードディスクから音声データを読み出す。」(表3)とあります。すなわち
• s:先頭の未使用ブロック番号
• t:未使用ブロック数
を与える必要があります。 -
s([ d ])の導出
未使用領域の先頭は使用中最後尾「p+m−1」の次のブロックです。よってs = p + mただしバッファはリング構造で「n−1に達したら、次はメモリブロックの番号が0」(バッファメモリの制御)となるため、Fig.4 では ([ d ] mod n) でラップさせています。結論:[ d ] = p + m -
t([ e ])の導出
総ブロック数は【問題文】「0〜n−1のn個」。このうち m 個が使用中なので未使用はn − mだけです。Buffering へ渡すブロック数は未使用ブロックを余さず全部読む必要があるため[ e ] = n − m -
以上から
d:p+m
e:n−m
が妥当であると示せます。
誤りやすいポイント
- 「p から m 個が使用中」を「p+m が最後尾」と読み違え、開始位置を p+m+1 としてしまう。
- 未使用ブロック数を「インデックス差」と誤解し n−m−1 としてしまう。
- リングバッファであることを忘れ mod n を考慮しない。
- Buffering が「一部の未使用ブロックだけを埋める」と勘違いし、t に固定値を置く。
FAQ
Q: p が n−1 のときでも d=p+m で良いのですか?
A: はい。Fig.4 では (d mod n) としており、n で割った余りを取るので自動的に 0 番に回り込みます。
A: はい。Fig.4 では (d mod n) としており、n で割った余りを取るので自動的に 0 番に回り込みます。
Q: m が 0 の場合はありますか?
A: 再生開始直後など Buffering 完了直後は m=n になるため 0 にはなりません。m が 0 になるのは再生が完全に停止しバッファを空にしたときです。この状態でデータ読出しタスクは動きません。
A: 再生開始直後など Buffering 完了直後は m=n になるため 0 にはなりません。m が 0 になるのは再生が完全に停止しバッファを空にしたときです。この状態でデータ読出しタスクは動きません。
Q: n−m が連続しない空き領域を越えて読むことは?
A: 使用中領域は常に連続(サーキュラバッファ方式)なので、未使用領域も連続し n−m 個を一括で読めます。結果的に追加読出しは一度の HDDRead で済み、余計なディスク回転を抑えられます。
A: 使用中領域は常に連続(サーキュラバッファ方式)なので、未使用領域も連続し n−m 個を一括で読めます。結果的に追加読出しは一度の HDDRead で済み、余計なディスク回転を抑えられます。
関連キーワード: サーキュラバッファ, 剰余演算, データストリーム, タスク間メッセージ, 省電力制御
設問3:
図3中のcの処理がない場合、ボタンの操作のタイミングによっては、ハードディスクの回転が長時間停止しなくなってしまうことがある。
cに入れる適切な字句を、20字以内で答えよ。
模範解答
c:データ読出しタスクの終了を待つ
解説
解答の論理構成
- 【問題文】の表3に「再生処理タスクが停止すると、このタスクも同時に強制的に終了させられる。」という記述があります。ここでいう「このタスク」とは表3の「データ読出しタスク」です。
- データ読出しタスクが HDD からデータを取得する一連の処理は、図5の Buffering(s, t) で示されます。Buffering の途中には【問題文】表1の関数 SpinUp() と StandBy() があり、StandBy() が実行されて初めてハードディスクの回転停止が指示されます。
- もし再生処理タスク側が dsp_end() 直後に自タスクを終了してしまうと、データ読出しタスクが Buffering の途中(SpinUp() と StandBy() の間)で強制終了される可能性があります。すると StandBy() が呼ばれず、【問題文】にある「ハードディスクは…読出しが終わったら回転を停止させる」という制御が実行されず、結果として「ハードディスクの回転が長時間停止しなくなってしまう」状態が発生します。
- したがって、STOP メッセージを受け取った再生処理タスクは、自身を終了する前にデータ読出しタスクが正常終了したことを確認しなければなりません。この待機動作を流れ図の c に入れる必要があります。
- よって c には「データ読出しタスクの終了を待つ」が入ります。これは再生処理タスクが HDD 制御の完了を保証し、ハードディスクを確実に停止させるために必須の処理です。
誤りやすいポイント
- 「再生処理が終わった時点で HDD 動作も終わっている」と早合点し、タスク同期の必要性を見落とす。
- Buffering(s, t) が常に短時間で終わると想定し、強制終了しても StandBy() が必ず呼ばれると誤解する。
- c に「StandBy() を呼ぶ」など関数呼出しを書いてしまい、タスクのライフサイクル制御が問題の本質であることに気付かない。
- 「2個以上同時に存在してはならない」という制約から c を「データ読出しタスクの起動を禁止する」と勘違いする。
FAQ
Q: dsp_end() を呼んだ後に HDD が回り続けるのはなぜですか?
A: HDD の回転停止は StandBy() によって行われます。再生処理タスクが先に終了すると、データ読出しタスクが StandBy() を呼ぶ前に強制終了されることがあり、結果としてモータ停止指示が出せません。
A: HDD の回転停止は StandBy() によって行われます。再生処理タスクが先に終了すると、データ読出しタスクが StandBy() を呼ぶ前に強制終了されることがあり、結果としてモータ停止指示が出せません。
Q: データ読出しタスクが存在しない場合でも c は必要ですか?
A: 必要です。存在しない場合は「終了を待つ」処理が即時に通過するだけで副作用はありませんが、存在する場合の安全動作を保証できます。
A: 必要です。存在しない場合は「終了を待つ」処理が即時に通過するだけで副作用はありませんが、存在する場合の安全動作を保証できます。
Q: READY メッセージと STOP メッセージの違いは何ですか?
A: READY は DSP が次のメモリブロックを処理する準備ができたことを示し、再生処理タスクは対応するデータ転送を行います。STOP は音声データの終端に到達したことを示し、再生処理タスク側で DSP 停止とタスク終了処理(c を含む)が行われます。
A: READY は DSP が次のメモリブロックを処理する準備ができたことを示し、再生処理タスクは対応するデータ転送を行います。STOP は音声データの終端に到達したことを示し、再生処理タスク側で DSP 停止とタスク終了処理(c を含む)が行われます。
関連キーワード: タスク同期, バッファリング, ハードディスク制御, SpinUp, StandBy


