Let's マイクロカーネル! 〜L4Ka::Pistachioで始めるマイクロな生活・導入編〜

ここではいくつかあるL4カーネルのうちL4Ka::Pistachioを既存のLinuxの上でコンパイルし, Qemuの上で動かすところまで解説します.
基本的な手順は公式サイト(http://l4ka.org/)の"Getting Started with L4Ka::Pistachio on ia32"というページを参照すればなんとか成りますが, いくつかおかしなところ(少なくとも私の環境ではだめだった)があったのでそこを適宜修正しつつ説明します.
なおここでは

OS : Linux 2.6.24-16, Ubuntu 8.04
CPU : Intel Celeron 1.466GHz (x86)

このような環境でテストしました

ソースコードの入手

Downloadのページに"Source Code Distribution"の項目がありtar.gz2形式にまとめられたものがありますが, ここではmercurial(hg)を用います

hg clone http://hg.l4ka.org/l4ka-pistachio

すると./l4ka-pistachio以下にこのカーネルソースコードが展開されます.

ビルド

ここからビルド作業になりますが, 少なくとも以下のツールが必要になります. Ubuntu 8.04には標準で入っていなかったので適宜インストールしておいてください.

  • autoconf
  • g++

ビルドの手順はカーネルのビルドとユーザランドプログラムのビルドの二つに分かれます.

カーネルのビルド

カーネルのソースはl4ka-pistachio/kernelに展開されています.このディレクトリで以下のようにmakeコマンドを実行し, ビルドの準備をします.

$ cd l4ka-pistachi/kernel
$ make BUILDDIR=$(pwd)/../x86-kernel-build

ここでBUILDDIRは絶対パスでなければならないようです. 次にここで指定したディレクトリに移動しビルドを開始します

$ cd ../x86-kernel-build/
$ make menuconfig

ここではHardware, Kernel, Debuggerの三つの項目について以下のように設定しました.

  • Hardware
  • Kernel
    • Enable Debugging mode に Y
  • Debugger
    • Kernel Debugger Console中のSerialPortとKeyboardをOnに

左右の矢印で移動, xで保存・終了になります.
設定が終わったら実際にビルド

$ make

同じディレクトリにできた"x86-kernel"というのがカーネルになります.

ユーザランドのビルド

カーネルコンパイルに必要なコード他がl4ka-pistachio/kernelにはいっているのに対し, ユーザランド用のそれは./user/にあります.
まずは, ここでconfigureを生成します.

$ cd l4ka-pistachio/user
$ autoheader
$ autoconf

ユーザランドのビルドはia32-user-buildというディレクトリを作りそこで作業を行います.

$ cd ../user/
$ mkdir ia32-user-build
$ cd ia32-user-build
$ ../user/configure --prefix=$(pwd)/../ia32-user-install --with-kerneldir=../x86-kernel-build/
$ make
$ make install

configureに対して--prefixオプションを指定しないと/usr/localに展開されてしまうのでここではl4ka-pistachio/ia32-user-installに展開するように指定しています.

ビルド完了

以上の手順でそれぞれ以下のディレクトリにコンパイルしたものが展開されます

  • カーネル : l4ka-pistachio/x86-kernel-build
  • ユーザ : l4ka-pistachio/ia32-user-install

公式ページの説明では以下のようにカーネル本体をユーザランドのものと同じところに持ってきています

cp l4ka-pistachio/x86-kernel-build/x86-kernel l4ka-pistachio/ia32-user-install/libexec/l4/

ブート

TFTPつかったりといくつかブートの方法はあるようですが, 簡単のためにここではgrubを用いたブートを行います. フロッピーのイメージファイルを作り, それを用いてQemu上でL4を実行します.

ここでは実機ですでにgrubが入っているものとします. なお GNU GRUB 0.97でここではテストしました.

GRUBの準備

grubとL4カーネルが入ったディスクイメージを作成するための作業ディレクトリとしてfdsourceを作成し、その中にgrubやらL4やらの必要なファイルを突っ込みます.

$ mkdir fdsource
$ mkdir -p fdsource/boot/grub
$ cp /boot/grub/stage1 fdsource/boot/grub/
$ cp /boot/grub/stage2 fdsource/boot/grub/

$ cp l4ka-pistachio/x86-kernel-build/x86-kernel fdsource;
$ cp l4ka-pistachio/ia32-user-install/libexec/l4/* fdsource/

これで, fdsourceの中は以下のようになります

$ ls fdsource
boot grabmem kickstart l4test pingpong sigma0 x86-kernel

さらにgrubのためにmenu.lstを作成します
(公式ページだとgrub.confに成っていますが、Ubuntu 8.04ではmenu.lstでないとだめなようです)

$ cat >> fdsource/boot/grub/menu.lst
root (fd0,0)
default=0
timeout=3
serial --port=0x3f8 --speed=115200
terminal --timeout=0 serial
title L4Ka::Pistachio
kernel /kickstart
module /x86-kernel
module /sigma0
module /pingpong
#module /l4test
^D

これで必要なファイルの配置が完了しました

ディスクイメージの作成

ここではQemuに食わせるために, FDのイメージファイルを作成します.

ddで適切なサイズのファイルを作り

$ dd if=/dev/zero of=fdimage.img bs=512 count=2880

ループデバイスとして設定し, ext2でフォーマット

$ sudo /sbin/losetup /dev/loop0 fdimage.img
$ sudo /sbin/mke2fs /dev/loop0

適当な位置にマウントして、先ほどのfdsourceの内容をコピーします.

$ sudo mkdir -p /mnt/fda
$ sudo mount /dev/loop0 -o loop /mnt/fda
$ sudo chmod 777 /mnt/fda
$ cp -aR fdsouce/* /mnt/fda
$ sudo umount /mnt/fda

最後にgrubの設定を行って、ループデバイスの解除

$ cat <

以上でディスクイメージの作成完了です

実行

Qemuに先ほどのFDイメージを食わせて実行します

$ qemu -fda fdimage.img


ね?簡単でしょ?

動きがない

今のところ上にのっているものが何にもないので動きが全くありません. "Launching Kernel"を表示されたら実際のところ終わりです.

これではあまりにも面白くないので, きちんと動いてそうなことを確認するためにqemu実行時にnographicオプションを付けます.

nographicオプション付きで実行

以下のようにターミナルに打つと

$ qemu -nographic -fda fdimage.img

先ほどとは打って変わって, エミュレートされたシリアルポートに対してL4カーネルが流しているデータをコンソールで見ることができます.カーネルコンフィグ時のSerial Portが有効になっていればここからデバッグメッセージなどを受け取れます.

図のようにLauching Kernelが表示されたあともいくつか動きがあります. ここで上記の番号のどれかを入力すると何かしらのテストが行われるようです.

pingpong

このテストの部分はもちろんユーザランドのプログラムとして実装されています.
先ほどのmenu.lstの中で以下のような記述がなされていました。

(略)
kernel /kickstart
module /x86-kernel
module /sigma0
module /pingpong
#module /l4test

kickstartはどうやらL4カーネルのスタートアップを担当するようなプログラムで, そいつがカーネル本体であるx86-kernelを立ち上げて, ルートページャ(?)のsigma0を立ち上げて, 最終的にpingpongとかいうプログラムを実行するらしい. pingpong意外にもl4testなどが用意されており, こちらを使うともう少し詳細なテストが可能なようだ


自前のプログラムを動かす

新規追加がどうもうまくいかないのでもともと入っていたgrabmemとかいうプログラムを勝手に書き換えてみた.

grabmem.cc

#include<l4io.h>
#include<l4/sigma0.h>
#include<l4/kdebug.h>

int main(void)
{
	printf("hello world¥n");
	return 0;
}

依然としてシリアルポートの方にしか結果が出力されないけど一応動く。

ただ、新しいプログラムの追加のしかたとかプログラミングガイドみたいな文章はどこかに無いものか・・・

まとめ

とりあえず動いた。でも次なにやろうか。
単体で手を出したせいかいまいちL4のビジョンが見えてこないので少し論文読んでみる。
あとLP49に手を出してみるか、あるいはちょうどMINIX本読書会が開かれるらしいのでMINIXとかに手を出してみると面白いかも。積んである本の消化にもなるし