平成30年度 春期 午前Ⅱ 問1
オペレーティングシステム
メモリマップドI/Oの問題
メモリマップド I/O の I/O ポートにアクセスするプログラムを C 言語で記述するときの注意点として,適切なものはどれか。
- アアセンブラの IN/OUT 命令を用いたアクセス用関数を呼び出して,アクセスする。
- イコンパイラによる最適化を抑止するために,volatile 型修飾子を付けて宣言した変数へのポインタとしてアドレスを指定して,アクセスする。
- ウ他の関数からアクセスされるのを防ぐために,静的広域変数として宣言してアクセスする。
- エポインタではアクセスできないので,配列として実体を宣言してアクセスする。
答えと解説を見る
✓ これが正解イコンパイラによる最適化を抑止するために,volatile 型修飾子を付けて宣言した変数へのポインタとしてアドレスを指定して,アクセスする。
解説
I/O ポートは volatile を付けたポインタで指し、最適化を防ぎます。
メモリマップドI/O では、I/O ポートのレジスタがメモリと同じアドレス空間に割り当てられているので、C 言語ではそのアドレスを指すポインタを通じて、普通のメモリと同じように読み書きします。ただし、コンパイラは、同じ変数を続けて読む処理を1回にまとめたり、値を使わない書込みを省いたりする最適化を行います。I/O ポートの値はプログラムの外で変わり、書込みそのものにも意味があるので、こうした最適化をされると正しく動きません。そこで volatile 型修飾子を付けて、毎回必ず実際のアドレスへ読み書きさせます。メモリと同じ番地で読み書きできることと、最適化を止めることの二つを押さえておくと、選択肢を見分けられます。
ほかの選択肢はなぜ違うのか
- アアセンブラの IN/OUT 命令を用いた…:IN/OUT 命令は、メモリとは別の I/O 用のアドレス空間をもつ方式で、ポートを読み書きするための専用命令です。メモリマップドI/O ではポートがメモリと同じ空間にあるので、専用命令を使わず通常のメモリアクセスで扱います。
- ウ他の関数からアクセスされるのを防ぐために…:静的広域変数として宣言しても、その変数の置き場所はコンパイラやリンカが決めるので、I/O ポートの決まったアドレスには割り当てられません。他の関数からの参照を絞ることと、最適化を止めることも別の話です。
- エポインタではアクセスできないので,配列と…:C 言語ではポインタに具体的なアドレスを入れれば、その番地へアクセスできます。配列として実体を宣言すると、ポートとは無関係なメモリ領域が確保されるだけで、I/O ポートには届きません。
出典:平成30年度 春期 エンベデッドシステムスペシャリスト試験 午前Ⅱ 問1
この解説に誤りを見つけたら教えてください。直して、直した記録を残します。誤りを報告する(メールが開きます)