メモリー空間を使い分ける仮想マシン
 ここでアプリケーションとWindowsサブシステムの関係を説明する前に,Windowsのメモリー管理について話しておく。

 Windowsアプリケーションが,実際に搭載しているメモリーより多くのメモリーを利用できるのは,仮想メモリーという技術を利用しているからだ。例えば,32ビット・プロセッサは,4Gバイトの物理メモリーを利用できるが,仮想メモリーの技術を利用すると,物理メモリーの容量とは関係なく,常に4Gバイトのメモリー空間を1つのプログラムに割り当てられる。なぜ,このようなことができるのかというと,プロセッサが持つ「ページング」機能を利用しているからだ。

△ 図をクリックすると拡大されます
図4●Windowsシステムの中に,仮想マシンが複数存在するイメージ
 32ビット・プロセッサのページング機能は,4Gバイトの仮想メモリー空間を1つのセグメントとして複数用意できて,そのセグメント・アドレスと実際の物理メモリー・アドレスを対応表で管理する。この対応表を「ページ・テーブル」と呼ぶ。そしてWindowsはページ・テーブルを利用して,仮想マシンごとに4Gバイトの仮想メモリー空間を割り当て,そのうち2Gバイトをアプリケーション領域に,残り2Gバイトをシステム領域に指定している。それはあたかもWindowsシステムの中に,4Gバイトのメモリーをもったコンピュータが,いくつも存在しているイメージになる(図4)。

 この図だけを見ると,ずいぶんぜいたくな作り方をしていると感じるかもしれない。4Gバイトものメモリー空間があれば,1つのセグメントの中に複数のアプリケーションを含めることも可能なはずだ。ただそうすると,クラッシュしたアプリケーションが他のアプリケーションの領域を破壊する可能性が出てくる。図のような構造なら,1つのアプリケーションがクラッシュしても,そのアプリケーションの仮想マシンごと削除するだけで,他のアプリケーションやシステムには影響を与えずに済む。

 しかし,実際にこのイメージの通りにシステムを作ろうとすると大変なことになる。すべての仮想マシンのメモリー空間に同じWindowsサブシステムを用意することになり,仮想マシンで非同期に実行されるAPIの協調を取るのは難しくなる。技術的には可能だが,メモリー容量の問題や起動時間など不利な点が多い。

△ 図をクリックすると拡大されます
図5●仮想マシン上のアプリケーションは,同じセグメントしかアクセスできない
 そこで実際のWindowsシステムでは,アプリケーションの仮想マシンとは別に,Win32 API用の仮想マシンを本当のWindowsサブシステムとして用意しておき,アプリケーション側には,ダミーのDLLを組み込んでいる。このようなDLLを「スタブDLL」と呼ぶ。そしてスタブDLLにアクセスがあると,本当のWindowsサブシステムのAPIが呼び出されるようにするのである。

 ところが,まだ問題がある。アプリケーションは,自分に割り当てられた4Gバイトの空間にしかアクセスできない。となると,このままでは別のセグメントにあるWindowsサブシステムのAPIは呼び出せないことになる(図5)。

仮想マシンをつなぐLPC

△ 図をクリックすると拡大されます
図6●LPCサービスの仕組み
 そこで登場するのが,カーネル・モードで動作するマネージャの一種「ローカル・プロシージャ・コール(LPC)」サービスである(図6)。仮想マシンで動作するアプリケーションが実行するAPIは,Windowsサブシステムの中にある。そしてWindowsサブシステムもまた,ユーザー・モードで動作する仮想マシンだ。

 そこで,この2つの仮想マシンの間を取り持つのが,ローカル・プロシージャ・コールである。

 ローカル・プロシージャ・コールと聞いて,よく似た言葉を思い出すかもしれない。そう「リモート・プロシージャ・コール(RPC)」だ。RPCは,2台のコンピュータを通信ケーブルでつなぎ,他方のコンピュータの処理を呼び出すことを指す。プロシージャとは処理の固まり,いわば関数のようなものだ。この仕組みは,ネットワーク上の異なるマシン同士で処理を実行するための手続きが起源となっていて,米Sun Microsystemsが開発したものである。

 つまり「リモート・プロシージャ・コール」と言った場合は,コンピュータ同士の通信を指すので,「ローカル」つまり同じコンピュータの中にある仮想マシン同士の通信を受け持つ機能ということで「ローカル・プロシージャ・コール」と呼んだわけだ。このように,コンピュータ間の通信技術がもとになっていることは,Windowsサブシステムの実行ファイル名が「Client Server Runtime Subsystem」の頭文字を取ったCSRSS.EXEであることからも推測できる。

 このように,最も重要なシステムの中心はカーネル・モードで保護し,アプリケーションはユーザー・モードの仮想マシンで実行する。そのアプリケーションが呼び出すWindows APIは,これまた別の仮想マシンに置いてあり,お互いはカーネル・モードが制御する通信技術で接続される。これがまさに,アプリケーション・クラッシュがWindowsのシステムにまで影響を及ぼさない本当の理由なのである。


大容量メモリーが使える
64ビットWindowsのアーキテクチャ

 現在のWindows XP ProfessionalやWindows Server 2003には,米Intelの64ビット・プロセッサ(Intel Extended Memory 64 Technology)と,米AMD(Advanced Micro Devices)の64ビット・プロセッサ(AMD Opteron/Athlon 64)に対応する64ビット・バージョンがある。この64ビット・プロセッサ向けのWindowsは「x64 Edition」と呼ばれ,価格こそ32ビット版と変わらないものの,処理性能が向上している。

 x64 Editionの特徴は,何といっても扱えるメモリーの容量が格段に増えたことだ。単純にアドレスのビット幅だけ見ても,プロセッサが扱える仮想メモリー空間は,32ビット版の4Gバイトから64ビット版の16Tバイトへと増大している。

 当然プロセッサ内のレジスタの大きさも64ビットになるため,32ビットを超える大きな値の演算にも有利だ。これによって,データベース・ソフトや通信ソフトなど,大きなデータを扱うアプリケーションが高速に動作する可能性が出てくる。

 もっともアプリケーション・メーカーにとって,64ビットOSの登場はうれしいことばかりでもない。アドレス空間やレジスタが64ビットになると,現在の32ビットのアプリケーションはそのままでは動かないからだ。中にはあらかじめ64ビットを視野に入れて開発を進めていたために,コンパイルし直すだけで動作するアプリケーションもあるかもしれないが,どちらにしてもコストがかかることには変わりがない。そこでマイクロソフトは,世の中が64ビット・アプリケーションに移行するまで互換性を確保するため,32ビット・アプリケーションも64ビットWindowsで動作する仕組み「Windows on Windows 64」通称「WOW64」を用意した。これはかつて16ビットWindowsから32ビットWindowsへ移行したときと同じ手法である。

 WOWの考え方は,Windowsの基本通り,仮想マシン上でアプリケーションを動作させる所にある。仮想マシン上なら実行中に,アドレス・ビット変換や命令の入れ替えを自由に行える。

△ 図をクリックすると拡大されます
図A●WOW(Windows on Windows)64の概要
 WOW64では,3つのDLLが重要な役割を担っている。まず「Wow64.dll」は,32ビット・アプリケーションからシステム・コールがあるとそれを横取り(フックと言う)する。ウインドウなどのGDIは「Wow64win.dll」がフックを担当する。また,64ビット・モードへ切り替えるのは「Wow64cpu.dll」の役割となる(図A)。

 ところでx64 Editionでは,当然ながら32ビット・アプリケーションだけでなく,ネイティブな64ビット・アプリケーションも動作する。そのためx64 Editionでは,レジストリは2種類用意され,WOW64がレジストリやファイル・システムのリダイレクションも行う。

 このように見ていくと,x64 Editionで,32ビット・アプリケーションを実行するのは,速度面で不利と感じるかもしれないが,そうとばかりも言えない。

 32ビットWindowsでは,仮想メモリー空間の4Gバイトのうち,半分はシステム領域となっている。それに対してx64 Editionでは,32ビット・アプリケーションも4Gバイトすべてを使用できる場合がある。システムは64ビットのプログラムなので4Gバイトより上のメモリー空間を使って動かせるからだ。すべてのアプリケーションに当てはまるわけではないが,大きなメモリー空間を扱うアプリケーションなら,x64 Editionの方が,高速に動作する可能性がある。