はじめに
BitVisor Advent Calendar の昨日分では保護ドメインのインターフェイスについて説明しました.
なんだか2日ぐらいカレンダーがずれているような気がしますが,たぶん気のせいでしょう.
え,今日ってクリスマスですよね?
というわけで,本日分では,保護ドメイン内からの入出力に使われている lineinput () と printf () について気を付けないとやばそうなことについて説明します.
lineinput (), printf () の用途
名前からある程度察せられるかと思いますが,これらは,普通のCプログラムでいうところの gets (), printf () のような使い方をします.
現在の BitVisor のコードでは,lineinput () は process/{shell,debug,monitor} で使われていて,キーボードやゲストからの入力を受け付けるようになっています.
printf () はいたるところで使われていますね.
注意点
わざわざ記事にしたには,それなりに言いたい注意点があったからです.
(決して前日の記事の後ろの方を切って分けたわけではない...はず)
何かというと,これら2つの関数は,ディスクリプタ0に入力用メッセージ経路 が,ディスクリプタ1に出力用メッセージ経路 が割り当てられていることを暗黙のうちに想定しています.
というか,コードの中にマジックナンバーで埋め込まれています(マクロですらありません).
例えば,printf () で最終的に呼び出される putchar () では,
void
putchar (unsigned char c)
{
msgsendint (1, c);
}
と,ディスクリプタ 1 にメッセージを投げています.
昨日の記事で,
- msgsenddesc () でプロセスにメッセージハンドラを紐づけます
- 第1引数に保護ドメインのプロセスディスクリプタ,第2引数にメッセージディスクリプタを指定します.
- 保護ドメインからはこの時登録した順に,0, 1, 2... とディスクリプタで参照できます.
と書きました.
つまり,保護ドメインの中でこう言った標準入出力的な関数を使いたい時には,
最初に標準入力用のメッセージディスクリプタを msgsenddesc () で登録,
次に標準出力用のメッセージディスクリプタを登録 する必要があります.
これ以外の順番で登録してはいけません,msgsenddesc() で登録する順番を変えたらうまく動かないはずです(試してはないですが)
おわりに
今日は保護ドメインの入出力についての注意点をを書きました.
僕は仕組みがわからなくて気持ち悪かったので調べたら,見つけてしまったという程度で,いろいろやってハマったりしたというわけでないですが,下手なことをするとたぶんハマるんじゃないかと思いますので気を付けましょう.