SSブログ

Windows 上の VirtualBox で実パーティション上の Linux を起動する [思想と科学]

新しい PC を買ってしまったせいで色々とセットアップをしている。引越し前だというのに。テスト前になると無性に掃除がしたくなるあの感覚と同じだな。
VirtualBox を使ってちょっと面白いセットアップをしてみたので、備忘録もかねてやり方を残しておく。そういえばこの手の技術(?)ネタって初めてかもね。実はエンジニアだったんですねワタクシ。

PC は Windows/Linux(Ubuntu) のデュアルブートにしているのだが、Windows で立ち上げている時にちょこっと Linux を使いたい場合がある。たとえば wget でバッチ的にファイルを落としたい場合なんかはシェルスクリプトを使いたい。あとはちょっとカーネルコンパイルしたい時とか(笑)。そんなときは仮想環境を使いたいわけだが、普通に Windows 上に仮想ディスクを作って Linux システムをインストールすると、既に Linux システム が入っているパーティションと Windows のディスク上の二箇所に似たようなシステムが存在することになってディスクの無駄遣いだ。ちょっと気の利いたスクリプトを書いて悦に入り、後日使おうと思ったらこっちのシステムにはコピーしてなかった、などという自分のアホさ加減を思い知らされる事態もできるだけ避けたい。
この課題をクリアするためには、Linux システム の入っている実パーティションを仮想マシンが rootfs としてマウントできればよい。VirtualBox にはその機能がある。すばらしい。

なお、Linux システムをネイティブで立ち上げて KVM で Windows を動かせば良いのでは?という意見も当然あるが、今回は二つの理由でそのアプローチを取らない。
理由1: Windows 上で使っている DTM ソフト(最近は DAW って言うのかな?)が結構マシンパワーを食うので、ネイティブ環境で実行したい。
理由2: 理由1により、Windows が入ったパーティションは残す必要がある。システムの二重化を防ぐためにはこのパーティションを仮想化環境から使うことになるが、Windows はハードウェアプラットフォームの違いに敏感なので、ネイティブ環境と仮想化環境で同じシステム(ディスクの内容)で実行できるか確信が持てない(そもそもアクティベーションし直しになるような)。Linux システムはその辺寛容で、多少ハードウェア構成が違っても適宜ドライバをロードして難なく走る。
(その昔、全然構成が違うマシンに HD を差し替えてブートしたら少々文句を言いつつも立ち上がってきて驚いたことがある)

VirtualBox で実パーティションを使う方法はマニュアルや、Web にもいろんなところに書かれているので要点だけ書いておく。

今回使用するディスクのパーティション構成は以下の通り。実ディスクは Grub2 を MBR に入れてブート選択を行っている。Grub の選択メニューを見ると、Linux システムは当然パーティション 6 から立ち上げるのだが、Windows はパーティション 2 から立ち上げて、パーティション 3 を C: として使うようだ。このパーティション 3 の Windows 上で VirtualBox を実行して、パーティション 6 の Linux システムを仮想マシンとして起動するのが今回の目的。
  • 1 (/dev/sda1): Recovery partition
  • 2 (/dev/sda2): Windows system reserved
  • 3 (/dev/sda3): Windows system (C:)
  • 4 (/dev/sda4): (Extended partition)
  • 5 (/dev/sda5): Windows data (D:)
  • 6 (/dev/sda6): Linux rootfs
  • 7 (/dev/sda7): Linux swap

VirtualBox から実パーティションを使う場合は、実ディスクのパーティション情報などを収めた仮想ディスク(ホスト上のファイル)を作成し、この仮想ディスクを仮想マシンのストレージとして割り当てる。仮想マシンで Linux システムを起動するためには仮想ディスクの MBR に Grub を入れる必要がある。そのためまずネイティブの Linux を立ち上げて、MBR をファイルとして保存する。
# dd if=/dev/sda of=sda.mbr bs=512 count=1


このファイルを Windows に持ってきてから、VirtualBox のコマンドで仮想ディスクを作成する。DOS 窓は管理者権限で実行すること。そうしないとディスクの作成に失敗する。
C:\Program Files\Oracle\VirtualBox>VBoxManage.exe internalcommands createrawvmdk
 -filename d:\virtualbox\raw_sda_ubuntu.vmdk -rawdisk \\.\PhysicalDrive0 -partit
ions 6,7 -mbr sda.mbr


これで実ディスクを反映した仮想ディスク raw_sda_ubuntu.vmdk が作成される。なお、仮想化環境からは Linux システム以外の実パーティションを触ってほしくない(というか、触られると壊れる)ので、パーティション 6 と 7 のみアクセス可能となるよう -partitions オプションを指定した。

さて、あとは仮想マシンを作成して raw_sda_ubuntu.vmdk をストレージとして割り当てれば、sda6 を rootfs として、つまりネイティブ起動時と全く同じ環境で Linux システムが立ち上がる。
めでたしめでたし。

・・・といいたいところだが、ここで問題、というか気に入らない点がひとつ。
当然ながら、Grub の設定ファイル(/boot/grub/grub.cfg)もネイティブ環境と仮想化環境で共有している。そのため Windows も Grub メニューに出てくるのだが、仮想化環境では必要ない。(Windows パーティションは中身を見せないように仮想ディスクを作ったので無意味)

ここからが今回の工夫どころ。この点を解決するため、/boot 用の仮想ディスクを作って VirtualBox ではここからブートするようにする。手順は以下。

  • VirtualBox の仮想メディアマネージャで仮想ハードディスクを作る。/boot なので 200MB もあれば足りるだろう。ここでは vb_boot.vdi として作成する。
  • 仮想マシンに vb_boot.vdi をストレージとして割り当てた後起動する。
  • vb_boot.vdi は /dev/sdb とかで見えているはず。(そのあたりは dmesg で確認) fdisk でパーティションの作成と mkfs.ext4 などでファイルシステムの作成(フォーマット)を行う。以降、こいつを「仮想環境用 /boot」と呼ぶ。
  • 仮想環境用 /boot ををマウントする。以下は ext4 でフォーマットした /dev/sdb1 を /boot_vb にマウントする例。
    # mount -t ext4 /dev/sdb1 /boot_vb
    
  • /boot の内容を仮想環境用 /boot にコピーする。
    # cd /boot
    # cp -a * /boot_vb
    
  • /etc/default/grub をお好みで書き換える。目的のためには GRUB_DISABLE_OS_PROBER=true なのだが、実は仮想化環境の Linux システムからは Windows システムが見えないように仮想ディスクを作成しているので、この書き換えはしなくても grub.cfg に Windows 用のエントリは作られない。今回はリカバリ用のエントリを消すため GRUB_DISABLE_LINUX_RECOVERY=true を指定したのと、Memory Test がうざいので /etc/grub.d/20_memtest86+ の実行属性を落としてエントリが作成されないようにした。
  • この後の二つの作業のため、仮想環境用 /boot を /boot にマウントし直す。/boot_vb にマウントしたままでも二重にマウントできるが、気持ち悪ければアンマウントしてからマウントする。
    # umount /boot_vb
    # mount -t ext4 /dev/sdb1 /boot
    
  • /dev/sda の MBR に Grub をインストールする。
    # grub-install /dev/sda
    
    これで /dev/sda の MBR にいる Grub は(仮想環境用 /boot):grub/grub.cfg を読み込むようになる。
  • /boot/grub/grub.cfg(今は仮想環境用 /boot の grub.cfg)を以下のコマンドで書き換える。
    # update-grub
    

これで OK。実マシンを起動する場合は Grub のメニューエントリに Windows, Linux の両方が表示されて選択可能だが、仮想マシンを起動した場合は Ubuntu しか出てこない。

だがしかーし!この方法にも以下の問題がある。
  • 仮想化環境でカーネルをアップデートすると、ネイティブ環境で立ち上げたときの Grub エントリからも Windos 用のエントリが消えてしまう。 仮想化環境では Windows 用パーティションが見えないので、/etc/grub.d/30_os-prober が Windows を見つけられないのだね。Linux システムを立ち上げることはできるので、ネイティブ環境で立ち上げて update-grub すれば直るけど・・・
  • 一方、ネイティブ環境でカーネルをアップデートした場合は、仮想環境用 /boot にそれが反映されない。ネイティブ環境では仮想ディスクなんて見えるわけないから当然だが。

これらは今のところしゃーないか、という感じ。カーネルをアップデートしたら、アップデート時と反対の環境への /boot のコピーと update-grub を忘れずに実行するってのが現状できることかな。
せめてもということで、仮想化環境で update-grub する手間を省力化するスクリプトを作っておいた。dmidecode で仮想化環境かどうか調べて、仮想化環境なら仮想環境用 /boot をマウント、実ディスク /boot と仮想環境用 /boot を同期、/etc/default/grub を書き換えて grub.cfg を生成、全部終わったら /etc/default/grub を元に戻すというもの。
/etc/kernel/postinst.d から実行して、ネイティブ環境と仮想化環境の grub.cfg を同時にうまいこと書き換えられるといいんだけど・・・今後の課題とします。

scrshot.jpg
んでお約束のスクリーンショット。VirtualBox はシームレスモードにしてあるので、Windows と Ubuntu のウィンドゥが混在している・・・だけならまだしも、Windows のタスクバーと GNOME のメニューバーが二列に並んでエラいことになってるなオイ。
右側の WikiPedia を出してる Chrome が Windows 上で、左側のターミナルと Ubuntu のページを出してる FireFox が Ubuntu 上で実行されている。ネットワークは NAT モードでつながるし、ホストの指定したディレクトリをゲストでマウントして共有できる、クリップボードが共有されているなど、なかなか便利。(便利機能はゲストに Guest Additions をインストールする必要あり)

続いてこちらもお決まりのベンチマーク結果。世界標準のベンチマークソフト「Linux カーネルコンパイル」で時間を計ってみた。ネイティブ環境と仮想化環境でかなり条件が違うので、参考程度に。

測定環境
  • CPU
    • Core i7 M620 (2.67GHz)
    • ネイティブ環境 ...2 cores, 4 threads
    • 仮想化環境 ... 2 cores, 2 threads
  • メモリ
    • ネイティブ環境 ... 8GB
    • 仮想化環境 ... 2GB
  • 仮想化設定
    • VT-x 有効
    • ネステッドページング 有効
  • ソフトウェア
    • ホスト ... Windows7 64bit
    • ゲスト ... Ubuntu 10.04 (kernel 2.6.32-24)
  • コンパイル対象: linux-2.6.35.5


時間かかるので、make allnoconfig; time make した結果を載せます(笑)。
「キャッシュ捨てる」と書いたのは make 前に echo 3 > /proc/sys/vm/drop_caches でページキャッシュを捨てた場合、「キャッシュ捨てない」は一旦コンパイルが終わった後に make mrproper; make allnoconfig してすぐまた make した場合です

測定結果
  • 仮想化環境
    • make: キャッシュ捨てる
      • real 2m14.481s
      • user 1m33.500s
      • sys 0m18.800s
    • make -j2: キャッシュ捨てる
      • real 1m32.091s
      • user 1m55.390s
      • sys 0m16.560s
    • make -j2: キャッシュ捨てない
      • real 1m11.100s
      • user 1m56.450s
      • sys 0m16.560s


  • ネイティブ環境
    • make: キャッシュ捨てる
      • real 2m8.108s
      • user 1m32.300s
      • sys 0m11.550s
    • make -j2: キャッシュ捨てる
      • real 1m21.167s
      • user 1m55.970s
      • sys 0m13.400s
    • make -j2: キャッシュ捨てない
      • real 1m1.354s
      • user 1m48.990s
      • sys 0m13.010s
    • make -j4: キャッシュ捨てる
      • real 1m3.407s
      • user 2m29.830s
      • sys 0m15.710s


流石にネイティブ環境よりは遅いけれど、高々 10% 程度のパフォーマンスヒットとはなかなかやるじゃないか。優秀優秀。
にしてもこの PC 速いな・・・技術の進歩ってやつでしょうか。

nice!(2)  コメント(0)  トラックバック(0) 

nice! 2

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

MIT Museum大陸横断ドライブ 0日目 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。