バイナリのロード
前回のエントリでプロセスを起動できるようになりました。
が、その動作確認には、Kernel内部のローダに対して、Kernel内部に定義したテスト関数のエントリを指定しているだけでした。
次のステップとしてはサーバプロセスの起動になりますが、そのためにはKernel外部にあるバイナリイメージの読み込みが必要になります。
従って今回は細かい移植不具合の修正を含め、独立して生成したテストプログラムのロードを確認してみました(リビジョン8)。
バイナリフォーマット
MonaOSでは、実行イメージのファイルフォーマットとして、
- ELF
- PE
をサポートしていますが、そのためにはフォーマット解析を担う各サーバプロセスの起動が必要になります。
このため、テストプログラムはrawバイナリとして直接ロードしてみます。
バイナリイメージの作成
MonaOSにはテストプログラム用のディレクトリが用意されていたため、そこを利用しました。
テスト用プロセスの出力形式はPEフォーマットとなっているため、rawバイナリで出力するようにします。
また、テスト用のコードは以下のようにしました。
int main(int argc, char* argv[]) { int i = 0; int pid = syscall_get_pid(); int tid = syscall_get_tid(); while(1) { _printf("pid:%d/tid:%d[%d]\n", pid, tid, i++); sleep(pid*100); } return 0; }
最初なので、簡単なところからです。
_printf関数は、デバッグ用のシリアルに対してprintを行うMona標準関数です。
バイナリイメージの置き場所
Kernelから見えるデバイス上に作成したバイナリを格納します。
MonaOSでは、FD(FAT12)やCD-ROMの外部記憶装置から順次、サーバプロセスを読み込み、起動していくようです。
Bishopエミュレータ上における今回の確認では、代替としてお手軽にNOR Flash(以下、NOR)にしてみました。
バイナリを格納する
エミュレートしているNORの内容を変更するには、直接qemuのソースコードの変更が必要ですが、qemuに手を入れるのは避けました。
思いついた一番簡単な方法としては、NOR上のinitrd用の領域を利用する事です。
Bishopエミュレータは起動時、(起動したディレクトリにある)特定のファイルを、NOR上の対応したアドレスにマップしているようです。
モジュール | ファイル名 | アドレス |
---|---|---|
ブートローダ | U-Boot.bin | 0 |
Kernel | uImage | 0x00040000 |
initrd | initrd.uimg | 0x00330000 |
現状、MonarmのブートローダとKernelはそれぞれ上記のファイル名にしているため、NOR上に配置され、アクセスできるためうまく起動しています。
テスト用のバイナリイメージもこの方法でいくため、initrd.uimgというファイル名にしました。
バイナリを参照する
次に、実際にKernelからNOR上のテストプログラムのバイナリコードを参照する方法に関してです。
MMUが有効であるため、仮想アドレス上にNORのアドレスをマップする必要があります。
NORは物理アドレス0番地からですが、0〜8MiBの領域はKernelの領域のため、ストレートにマッピングする事はできません。
従って、以下のようにストレートにマップしているI/O領域直前の4MiBにマップしました。
マップすべき本当に必要な領域はinitrd用の領域の部分のみですが、NORのサイズは4MBなので全てマップしてしまいました。
またKernelからは、0x47c00000+0x00330000のアドレスをエントリポイントとしてプロセスをロードするようにします。
そうすれば作成したテストプログラムがプロセスとして起動するはずです。
実行
make後qemuを実行すると以下のログが出力され、プロセスがロードされた事を確認できました。
% qemu-system-arm -M pe201b -serial stdio -mtdblock null.fs -nographic Mona version.0.3.0Alpha9 on ARM920T(S3C2440A/Bishop) Aug 25 2008 00:28:52 Setting PIC [OK] System Total Memory 64[MB]. Paging on mainProcess:Load#1:Success(0) mainProcess:Load#2:Success(0) mainProcess:Load#3:Success(0) pid:5pid:4pid:3/tid:58/tid:60[0] [0] /tid:59[0] pid:3/tid:58[1] pid:4/tid:59[1] pid:5/tid:60[1] pid:3/tid:58[2] pid:4/tid:59[2] pid:3/tid:58[3] pid:5/tid:60[2] pid:3/tid:58[4] pid:4/tid:59[3] pid:5/tid:60[3] pid:3/tid:58[5] pid:4/tid:59[4] ・・・(数分後)・・・ pid:5/tid:60[2415] pid:3/tid:58[4012] pid:4/tid:59[3015] pid:3/tid:58[4013] pid:5/tid:60[2416] pid:4/tid:59[3016] pid:3/tid:58[4014] pid:3/tid:58[4015] pid:4/tid:59[3017] pid:5/tid:60[2417] pid:3/tid:58[4016] pid:4/tid:59[3018]
プロセス起動開始直後、表示が乱れているのはログ出力がシリアライズされていないためです。
おわりに
Kernel外部のバイナリイメージを起動する事が確認できました。
これによって、以降目標としている従来のサーバプロセスの起動に失敗した場合、
- Kernel側のロードシーケンスに問題があるのか
- またはサーバプロセス側のスタートアップ以降の処理に問題があるのか
の切り分けがしやすくなると思います。
追記
確認では、同じコードを3回ロードするようにしています。
(明記が漏れていました)