Xv6を使ってみる

Xv6 というのは、マサチューセッツ工科大の院生向け教材として、UNIX V6 を ANSI の C で書き直し、x86 CPU 向けに書き直したオペレーティング・システムです。

講義用の資料とソースコード、ビルド環境( MakeFile や QEMU オプション )などの一式が、無料で公開・配布されています。 詳しい情報は、下記のページを参考にしてください。

なお、V6 を含む UNIX のソースコードは次の URL で BSD ライセンスのもと公開されています。

クイック・スタート

とりあえず動かしてみます。C の x86 コンパイラセットと、QEMU、Git 環境を整えます。最近の Linux ディストリビューションでしたら、コマンド数個をタイプするだけで完了です。 公式ページのとおり、ソースコードを clone します。

$ git clone git://pdos.csail.mit.edu/xv6/xv6.git

カレントディレクトリに xv6 ディレクトリが作成されます。xv6 ディレクトリに移動し、中身を覗いてみると、ちゃんとソースコードが clone されています。

$ cd xv6/
$ ls
BUGS initcode.S kalloc.c sh.c asm.h types.h LICENSE swtch.S
kbd.c spinlock.c buf.h user.h Makefile trapasm.S kill.c
stressfs.c defs.h x86.h Notes usys.S lapic.c string.c elf.h
toc.hdr README bio.c ln.c syscall.c fcntl.h kernel.ld TRICKS
bootmain.c log.c sysfile.c file.h runoff.list cuth cat.c ls.c
sysproc.c fs.h sleep1.p dot-bochsrc console.c main.c timer.c
kbd.h symlink.patch gdbutil echo.c memide.c trap.c memlayout.h
pr.pl printpcs exec.c mkdir.c uart.c mmu.h sign.pl runoff
file.c mkfs.c ulib.c mp.h vectors.pl runoff1 forktest.c mp.c
umalloc.c param.h runoff.spec show1 fs.c picirq.c usertests.c
proc.h spinp grep.c pipe.c vm.c spinlock.h bootasm.S ide.c
printf.c wc.c stat.h entry.S init.c proc.c zombie.c syscall.h
entryother.S ioapic.c rm.c toc.ftr traps.h

Makefile があるので、make でビルドできるんでしょう。中身を見てみると、qemu 実行オプションが記載されていました。 試しにビルドして、実行してみます。

$ make qemu-nox

キャラクタ端末経由で実行してみたい為、qemu' ではなくqemu-nox’ と指定してみました。前者で実行すると、SDL ウィンドウが表示されフレームバッファによる描写が行なわれると思います。

$ qemu -nographic -hdb fs.img xv6.img -smp 2 -m 512
xv6...
cpu1: starting
cpu0: starting
init: starting sh
(xv6)$ 

ビルドが完了すると、上記のように QEMU が非グラフィックモードで起動してシェルが起動してくれます。 試しに ls をタイプして実行してみます。

$ ls
.              1 1 512
..             1 1 512
README         2 2 1929
cat            2 3 10532
echo           2 4 10005
forktest       2 5 6533
grep           2 6 11876
init           2 7 10334
kill           2 8 9993
ln             2 9 9987
ls             2 10 11699
mkdir          2 11 10066
rm             2 12 10055
sh             2 13 18467
stressfs       2 14 10537
usertests      2 15 40448
wc             2 16 10870
zombie         2 17 9779
console        3 18 0
$ 

ちゃんと動作している模様。ちょっと遊んでみます。

(xv6)$ ls | wc
19 76 468
(xv6)$ grep you README
If you spot errors or have suggestions for improvement, please send
On non-x86 or non-ELF machines (like OS X, even on x86), you will
To run xv6, you can use Bochs or QEMU, both PC simulators.
(xv6)$ echo hoge > fuga
(xv6)$ cat fuga
hoge
(xv6)$ rm fuga
(xv6)$ ls fuga
ls: cannot open fuga
(xv6)$    

ちゃんとパイプもリダイレクトもサポートしているシェルのようです。MINIXのようでカワイイですね。

ユーザプログラムを追加してみる

さすが教育用といったところか、ドキュメントもツールも非常に分かりやすいものが準備してあるので、独自のプログラムを追加してみます。

まず、xv6 のディレクトリに以下のような hello.c を作成します。

#include "types.h"
#include "stat.h"
#include "user.h"
int main(int argc, char *argv[])
{
    printf(1, "hello, world\n");
    exit();
}

echo.c をコピーして修正してみました。ここに登場する printf() は stdio のものではなく、独自に定義されたものです。その為、第一引数が sprintfl() のようなファイルディスクリプタになっているようです。 深くソースを追っていませんが、今回は標準出力に吐きたいので “1” を指定してみました。

次に、Makefile の UPROGS に _hello を追加します。

UPROGS=\
_cat\
_echo\
_forktest\
_grep\
_hello\
_init\
_kill\
_ln\
_ls\
_mkdir\
_rm\
_sh\
_stressfs\
_usertests\
_wc\
_zombie\

これで、ビルドの準備は整いました。シェルから以下のコマンドを実行すると、hello.c を _hello に単体ビルドしてくれます。

make _hello

エラーが表示されなければ、無事 _hello という名前のバイナリが出力されたかと思います。 また、ユーザコマンド一式を一括ビルドし、ファイルシステム・イメージ fs.img を作成するには、以下のようにタイプします。

make fs.img

ビルドが上手くいったら、先程と同様に QEMU を用いて確認します。

$ make qemu-nox
xv6...
cpu1: starting
cpu0: starting
init: starting sh
(xv6)$ ./hello
hello, world
(xv6)$ 

無事、”hello, world” と表示されました。 なお、シリアルモードの QEMU で C-a h をタイプすると簡易ヘルプが表示され、C-a c で QEMU コンソールに切り替わり、 C-a x でエミュレータを終了します。

※ 2020/07/02 度重なるブログ移転・ブログシステムのアップデートにより崩れた記事を校正。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください