Linuxemu: OSエミュレータ

前回紹介したLinuxemuは、Plan9LinuxをエミュレーションするOSエミュレータである。OSエミュレータは主にシステムコールをエミュレートするのが仕事で、機械語命令はそのまま実行する(というかOSエミュレータは何もしない)。つまり、システムコールを発行しない、純粋な計算などは、ネイティブと同じ速度で実行できる。OSエミュレータには、LinuxWindowsをエミュレーションするWINEや、FreeBSDLinuxエミュレーション、MachUNIXサーバなどが存在する。

マイナーOSから見たOSエミュレータの利点は、ターゲットOSの豊富なアプリケーションを(バイナリしかなくても)そのまま動かすことができることだが、ソースコードが提供されていても、移植の手間を考えるとメリットは大きい。

OSエミュレータの原理自体は単純で、システムコールをトラップする部分と、発行されたシステムコール、つまりopenならopen、readならreadの処理をエミュレートする部分に大別できる。が、原理はわかっても、大量のシステムコールすべてに対応するのは、非常に泥臭く、大変な作業になる。Urielさんは、これを称して創造的マゾヒズムと言っている(笑)

linuxemuはターゲットとなるELFバイナリをメモリ上にロードして、スタックを準備し、note*1ハンドラを登録した後、ターゲットのエントリポイントへジャンプする。エントリポイントから実行が開始され、Linuxシステムコール呼出しのためにint 0x80命令が実行されると、例外が発生し、カーネルへ遷移する。そして、linuxemuに対して、カーネルからnoteが通知され、ハンドラが実行される。ハンドラの中では、システムコール番号を基に、対応するシステムコール処理を表引きして、それを実行した後、int 0x80直後の命令から実行を再開する。

上記の処理に相当するコードがlinuxemu.cで、ELFローダがload.c、sys*.cはシステムコールをエミュレートするコードである。

*1:UNIXではシグナルに相当する。