基盤ソフトウェア 4/24

相変わらず学生に対して答えにくい質問を連発します。

仮想マシン(Virtual Machine)

歴史的にはマルチタスクよりも先に出てきた
アプリケーションが複数動けばよかった
しかしマルチタスクが一般的になってくると消えてしまった
VMマルチタスクと似ている
仮想マシン <= OSのMultitasking + α
歴史的な順番は違うけれど…

そもそもマルチタスクとはなにか
短い時間でアプリケーションを切り替えて同時に動いているようにみせる
今はマルチコアも一般的

どうやって短い時間で切り替えているのか
アイディアとしては単純
マルチタスクを動かすコンピュータには必ずタイマーが入っている
タイマ割り込みをかける
それまで動いていたプログラムを強制的にストップして
別のプログラムが動き始める
一般的なOSはそれ以外の状況でも切り替わる
例えばIOなどでも切り替わる
ディスクアクセスが終わるまで違うプログラムを動かすとか…
ファイルアクセスをするときはOSに頼まなければならない
データの整合性、セキュリティ、プロテクション
違う誰かによって勝手に覗かれない
結構頻繁にOSを呼び出すので
マルチタスクが実現されている

VMでも同じ方法でできるはず
OSのカーネルコードといってもプログラムには違いない
タイマ割り込みかけてこっちのOS、今度はこっちのOS、というふうに
短い時間で切り替えながら動かすというのは一緒

普通のプログラムとカーネルは
特権命令を実行できるかできないかという点で異なる
特権命令がないとアプリケーションプログラムが勝手にIOを動かしてしまう危険がある
アプリケーションが特権命令を実行しようとするとOSのカーネルから実行される
プロセッサの中に特権かそうでないか、
どちらのモードで動いているかをあらわすレジスタがある

VMの+αの部分には特権命令がある
特権命令をどうやって仮想化するか
VM上のOSは、当然自分が特権命令が動かせると思っている
VM上で動いているOSに特権命令を与えるという方法があるが、
これをやってしまうと大混乱に陥ってしまう
タイマ割り込みも特権命令
次にどのプログラムを動かすか登録する
みんながこれをできてしまうと大混乱

だからVM上のOSには特権命令を与えてはいけない
特権モードをエミュレーションする
偽者の特権モードを与える
これが仮想マシンを作るうえでは一番重要
あとは普通のマルチタスクと同じ方法でいける

Intel x86
特権モードでは1つではなく何種類かある
Ring3 user
 :
 :    guest OS VMはここで動かせばいいんじゃないか?
 :             しかしそうは問屋が卸さない
 :             普通のOSはRing0で動くことを想定している
 :             Intelはそういう状況を考慮してRing1と2を用意したのに誰も使っていない
Ring0 kernel

user modeで特権命令を実行すると割り込みが発生
割り込みの先でエラーメッセージやログファイルを出したり終了させる
ここがエミュレートのポイントになる

         | アプリケーション|
         |-----------------|
ユーザー | Guest OS        |
                                                                • -
特権 | 本物OS GuestOSは当然自分が特権モードで動いていると思っているので 特権命令を実行しようとして割り込みがかかる 割り込んだ先で本物の特権命令をエミュレート 例えば本物OSのIOを使ってもいいけど あんまり無茶苦茶なことにならないように適当に調整する フルエミュレーション x86の命令を1命令ずつ動かす 例えばファミコンのエミュレート ある種のシミュレーション ソフトウェア的に1命令ずつ実行する ヨーロッパで売っているPS3はソフトウェアでPS2をエミュレートしている フルエミュレーションよりも 同じハードウェア上で実現されているエミュレータの方が高速 VMwareParallelsなど 仮想マシンといってもそんなに遅くない プログラムの大半はハードウェアで直接実行 特権命令だけソフトウェアで実行する 特権命令が出てこない限りにおいては直接動かしている場合と同じスピードで動く 特権命令をソフトウェア的にやる、 といっても話は簡単ではない 例えばDiskImageというでっかいファイルにアクセスするなど 適当な読み替えをしてやらなければならない この部分でオーヴァヘッド VMwareでOSを動かすと なんだかグラフィックが遅い ディスクアクセスなども遅い 特権命令が出てくると途端にスローダウンする 割り込みが発生すると割り込みが発生しただけで1000サイクルくらい消費される とにかくたくさん 割り込みの数が性能に効いてくる 100倍とか1000倍遅くなる どれだけ割り込みをやらずに済むかにスピードがかかっている というわけで商用の仮想マシンを作る場合には 割り込みをいかに減らしてスピードアップするかが勝負 もう1つ考えなければいけないのは ユーザモードで特権命令を実行すると割り込みが発生するが 実は本物のx86は割り込みをスルーする場合もある リアルに動く仮想マシンを作ろうとするとこれも結構ネック これをどういうふうにするかも重要な問題 クラシックなやり方は Guest OSが読み込まれたら全部のプログラムを調べて 割り込みを発生しない特権命令を見つけたら 割り込みを発生する特権命令に置き換える プログラム書き換え これはVMwareの特許らしい 自動的に書き換えるのは特許ならば手で書き換える 実行中に書き換えないで実行前に書き換える Xenなど IntelはVTというアーキテクチャをつくって VTがONになっていると 今まで割り込みが発生しなかった特権命令でも割り込みが発生するようにする 割り込みが発生するとRing-1に落ちる 最初はIntelは何も助けてくれなかったのでソフトウェアで動かしていた メジャーな機能になってくるとハードウェアがサポートするようになる IntelはVTを売りたくて仕方ない しかし VMware「わが社のVMはVTをONにしているとかえって遅くなる」 と記者会見を行った VMwareは特許があるのであまりVTなんてやってほしくないのではないか 個人的な推測だが… なぜ遅いかというと ソフトウェアなら簡単な処理であれば割り込みを発生させないということもできる 普通はハードウェアに頼ったほうが早くなるものなのだけど この件に関して言うとソフトウェアの方が賢い でも実装はすごく複雑になるので安定して動くかどうかが心配になる