COW: Copy-On-Write
非常によく似た複数の仮想マシンがあったとする。できれば、それらすべての仮想マシンには同じルートファイルシステムを使わせたい。そうすれば多くの領域を節約できるからだ。とはいえ、こうした考え方ではうまく行かない。それは、すべての仮想マシンがこの共有されたイメージに対して書き込みを行う可能性があり、そうすると他の仮想マシンで問題が起こるためである。では書き込み可能なファイルシステムをそれぞれの仮想マシンに持たせてはどうかと考えたくなるが、そうすると仮想マシンごとにファイルのコピーを作ることになるので、多くのディスク領域が消費されてしまう。それでいて各ファイルの類似性が非常に高く、内容にほとんど違いがない可能性もあるのだ。
UMLは、こうした問題をCopy-on-write(COW)と呼ばれる機能によって解決している。COWの基本的な考え方は、1つの仮想ブロックデバイスを2つのファイルで構成できるというものだ。一方は読み取り専用ですべての共有データを持ち、他方は読み書き可能で個別の変更内容のすべてを格納する。UMLカーネルの起動時にubdb=cowfile,sharedfileと指定することで、cowfileというファイルに変更内容を書き出し、もっとサイズの大きい読み取り専用データはsharedfileを使って共有する、/dev/ubdbデバイスが用意される。ここで留意すべき重要な点は、cowfileにはほとんど中身がないことだ。一見するとsharedfileと同じサイズのように思えるが、ls -lsを実行すれば非常に小さなファイルであることがわかる。
host% ls -lsh cowfile 2.9K -rw-r--r-- 1 marc marc 1.6G Dec 22 16:58 cowfile
1.6GBというサイズが目に入るものの、実はディスク上の占有バイト数がわずか2.9KBに過ぎないことを最初のカラムが示している。COWファイルシステムにアクセスする際のパフォーマンスを比較計測するテストは行わなかったが、理論上はCOWの利用によってパフォーマンスは向上する可能性が高い。ホストシステムは同じデータに対して2つのコピーをキャッシュする必要がなく、物理メモリを節約できるためだ。
COWの詳細については、UMLのWebサイトにある「Sharing Filesystems between Virtual Machines(複数の仮想マシンでファイルシステムを共有する)」のページを参照してもらいたい。
hostfsを使って仮想マシンから物理ホストマシン上のファイルにアクセスする
UMLには、仮想マシンから物理ホスト上のファイルにアクセスする方法がいくつか用意されている。一番簡単な方法はhostfsを使うことだ。ゲスト側で次のコマンドを実行すると、ホストファイルシステム全体が仮想マシン内の/hostとして利用できるようになる。
mount -t hostfs none /host
次はもう少し複雑な例で、ホストファイルシステム上にある特定のディレクトリを1つだけマウントする方法を示している。
mount -t hostfs none /home/marc -o /home/marc
hostfsを用いる方法には制限があるため、そうした制限の一部を解消したhumfsという別の方法も存在する。hostfsとhumfsの詳細については、UMLのWebサイトにある「Host File Access page(ホスト側ファイルへのアクセス)」のページを参照していただきたい。
自作のUMLカーネルを構築する
これまでに紹介したのはコンパイル済みゲストカーネルをダウンロードしてUMLを使用する方法だったが、独自のUMLゲストカーネルを構築することもできる。最近のカーネルバージョンを使うなら、ホストLinuxカーネルをコンパイルするほど難しくはない。
ゲスト側で使うLinuxカーネルのソースコードは、kernel.orgからダウンロードするか、該当するLinuxディストリビューションの関連パッケージをインストールするかして入手する。バージョン2.6.9以降のLinuxカーネルのソースコードを使えば、比較的簡単にUMLゲストカーネルを構築できる。カーネル2.6.9以降にはUMLサポート機能が組み込まれているからだ。
それよりも古いカーネルだと適切なパッチのダウンロードと適用が必要になるので、できるだけ最近のカーネルを使うことをお勧めする。ダウンロードしたカーネルのソースコードは、普通に解凍と展開ができる。通常のカーネルと比べてUMLゲストカーネルのコンパイルが大きく違うのは、makeコマンドにARCH=umを追加しなければならない点だ。たとえば、デフォルトUMLカーネルの設定とカスタマイズの後、UMLカーネルの構築を行うための典型的なコマンド系列は次のようになる。
make defconfig ARCH=um
make menuconfig ARCH=um
make ARCH=um
カーネルの構築が完了すると、「linux」という大きな実行ファイルができる。このファイルが巨大なのは、デバッグ用シンボルを含んでいるためである。デバッガを使う予定がなくてカーネルのサイズを縮小したければ、stripコマンドを使ってデバッグ用シンボルを取り除いても構わない。新しいカーネルを走らせるには、先に説明したように、該当するルートファイルシステムファイルを含むファイルをパラメータubda=の後ろに指定して./linuxを実行すればよい。たとえば次のようになる。
./linux ubda=FedoraCore5-x86-root_fs
UMLカーネルの構築について詳しく知りたければ、UMLのWebサイトにある「Building from source(ソースからの構築)」のページを参照するとよい。
