AsiaBSDCon 2018 で linux rumpkernel についての発表があったらしく気になっていた。
www.slideshare.net
当日は参加していないのでわからないが、linux kernel をライブラリとして使ってユーザーランドでネットワークの実装を簡単に行いたいという文脈なのだろうか。
プロジェクトのサイトは https://lkl.github.io/ だが非常に簡素、というか情報がないので、 直接リポジトリを見たほうが良い。
README の FAQ に UML (user mode linux) との違いが書いてあるが、UML はフルのカーネルがユーザーランドで動いているが、 lkl はあくまで自分のコードとリンクして kernel の関数を呼び出すということが主眼になっている。
tools/lkl の中にいくつかサンプル的なコードが散らばっているので見てみるとだいたい使い方はわかる。 hijack ライブラリを使うと LD_PRELOAD を使って libc の syscall を置き換えて lkl の syscall を使わせることができる。 すべての syscall を置き換えているわけでは無いので何が使えるかはコードを見る必要がある。 また lkl で置き換えていない syscall はホスト側が使われるようだ。
lkl 自体は arch の一種として実装されているようだ。 UML も同様だったし linux kernel はこのあたりよく抽象化されている。
実際に lkl をつかって procfs をマウントし内部のファイルを出力するサンプルを書いてみた。 https://github.com/toshipp/play-with-lkl/blob/master/cat_proc.c
lkl の初期化に lkl_start_kernel
を呼び出して、lkl のシステムコールを使うには lkl_sys_*
を呼び出せば良い。
lkl_start_kernel
の引数の lkl_host_ops
は lkl が使うホストシステム側のシステムコールなどを保持する構造体で、
posix では以下で実装されている。
https://github.com/lkl/linux/blob/master/tools/lkl/lib/posix-host.c
この構造体を書き換えてやれば posix 以外でも動くだろう。 実際に windows 用のコードもある。
さて、lkl は NOMMU として実装されているが、NOMMU でも vfork はサポートできる。 ただし lkl は vfork を未実装にしているので試しに有効にして使ってみた。
https://github.com/toshipp/play-with-lkl/blob/master/patch/vfork.patch https://github.com/toshipp/play-with-lkl/blob/master/vfork.c
残念ながらこれを起動すると segv で落ちてしまう。
% ./vfork (git)-[master] [ 0.000000] Linux version 4.15.0+ (toshi@toshi-note) (gcc version 7.3.1 20180312 (GCC)) #2 Sat Apr 14 20:25:56 JST 2018 [ 0.000000] bootmem address range: 0x7f776f396000 - 0x7f776fd95000 [ 0.000000] Built 1 zonelists, mobility grouping off. Total pages: 2524 ... [ 1.380143] Btrfs loaded, crc32c=crc32c-generic [ 1.380235] Warning: unable to open an initial console. [ 1.380261] This architecture does not have kernel memory protection. zsh: segmentation fault (core dumped) ./vfork
core を見てみると vfork から最終的に呼び出される copy_thread で使う関数ポインタが NULL になっているようだ。 https://github.com/lkl/linux/blob/master/arch/lkl/kernel/threads.c#L179
もしかするとなんとかできるのかもしれないが、よく考えると vfork なんて使わなくても、 lkl 呼び出し側のコードで pthread_create などを使えば良いだけだと気づいたので深追いはしていない。