Hyper-VマネージャーでWindowsのVMを作ると、起動には数十秒かかり、数GBのメモリが専有されます。ところが同じPCでwslと打てばLinuxのシェルが数秒以内に返り、Windows Sandboxも数秒で使い捨てのデスクトップを開きます。1
どちらも土台は同じWindowsハイパーバイザーです(第1回「あなたのWindowsはどこで動いているのか」)。第2回では、この土台が「カーネルより強い隔離」を作れることを見ました。それなのに、なぜ片方は重く、片方は軽いのでしょうか。
連載最終回が答える疑問は、ただ1つです。
フルVMは重いのに、WSL2やWindows Sandboxはなぜ軽いのか。
対象読者は、WSL2・Windows Sandbox・Windowsコンテナーを開発や検証に使っていて、その軽さと制約を仕組みから理解したい開発者・運用担当者です。前提環境はWindows 10/11で、Windows Sandboxの節の実演にはPro・Enterprise・Educationのいずれかのエディションが必要です(HomeやWindows Serverにはこの機能がありません)。前提知識は第1回のパーティションの概念です。難易度は中級です。
1. まず結論
軽量VMは、隔離の線(専用カーネル・ハイパーバイザー境界)は保ったまま、「ゲストOS一式の複製」を軽くした。SandboxはホストのWindowsそのものを共有し、WSL2はゲストを用途特化の小さなLinuxに置き換え、メモリはどちらも固定予約ではなくホストと動的に融通する。
フルVMの重さの源泉は、隔離そのものではなく複製です。ディスク上にもう1つのOSイメージ、RAM上にもう1つ分のOSページ、起動のたびにもう1回のフルブート。軽量VMたちはこの複製を、「共有しても安全なものは共有する」(Sandbox)、「共有できないなら小さく作り直す」(WSL2)という2つの方針で削ります。
flowchart TB
accTitle: 軽量VMを支える3つの共有
accDescr: フルVMが複製していたOSイメージはSandboxでは共有・WSL2では小型化で削り、固定割り当てが基本(動的メモリ構成は例外)のメモリはホストとの動的な融通に、起動は軽量カーネルと最小構成に置き換えて、隔離の境界だけを残す
heavy["フルVMの重さの源泉は複製"] --> d1["ディスク:OSイメージの複製"]
heavy --> d2["メモリ:固定割り当てが基本"]
heavy --> d3["起動:フルブートのやり直し"]
d1 -->|置き換え| s1["共有(Sandbox)や小型化(WSL2)"]
d2 -->|置き換え| s2["ホストと動的に貸し借り"]
d3 -->|置き換え| s3["軽量カーネルと最小構成で短縮"]
図1: 隔離をやめたのではなく複製をやめたことが、「同じハイパーバイザーなのに軽い」の答えの骨格である。
以下、WSL2、Windows Sandbox、コンテナーの順に、それぞれがどの複製を削っているのかを見ていきます。
この記事の知識マップ
WSL2は軽量ユーティリティVMの中で本物のLinuxカーネルを動かし、VM全体は.wslconfigで構成できる。キャッシュメモリの回収は実験的設定autoMemoryReclaimが制御し、OS境界を越えるファイルI/Oを避けるため、ファイルは操作するツールと同じOS側に置く。Windows Sandboxは動的ベースイメージでディスクの複製を避け、それを前提とするダイレクトマップでメモリフットプリントも抑え、既定で有効なネットワークなどは.wsb構成ファイルで制御する。Windowsコンテナーの分離モードのうちセキュリティ境界とされるのはHyper-V分離のみで、信頼できないコードの実行にはプロセス分離ではなくHyper-V分離を選ぶ。Hyper-V VMの中でWSL2を動かす場合は、1段の入れ子の仮想化がサポートされる。
flowchart LR
accTitle: WSL2・Windows Sandbox・コンテナーの知識マップ
accDescr: WSL2が軽量ユーティリティVMとLinuxカーネルを使い.wslconfigで構成され、Windows Sandboxが動的ベースイメージとダイレクトマップでホストと共有し、コンテナーはHyper-V分離だけがセキュリティ境界となる関係図
wsl2["WSL 2"]
windows_sandbox["Windows サンドボックス"]
container_process_isolation["プロセス分離"]
container_hyperv_isolation["Hyper-V分離"]
lightweight_utility_vm["軽量ユーティリティVM"]
linux_kernel["Linuxカーネル"]
wslconfig[".wslconfig"]
wsl2_cached_memory["WSL2のキャッシュメモリ"]
automemoryreclaim["autoMemoryReclaim設定"]
dynamic_base_image["動的ベースイメージ"]
direct_map["ダイレクトマップ"]
memory_footprint["メモリフットプリント"]
wsb_configuration_file[".wsb構成ファイル"]
security_boundary["セキュリティ境界"]
untrusted_code_execution["信頼できないコードの実行"]
nested_virtualization["入れ子の仮想化"]
disk_footprint["ディスクフットプリント"]
namespace_isolation["名前空間の分離"]
same_os_file_placement["同一OS側へのファイル配置"]
cross_os_file_access["OS間ファイルアクセス"]
wsl2 -->|"利用する"| lightweight_utility_vm
wsl2 -->|"利用する"| linux_kernel
wsl2 -->|"で構成できる"| wslconfig
wsl2_cached_memory -->|"で構成できる"| automemoryreclaim
windows_sandbox -->|"利用する"| dynamic_base_image
windows_sandbox -->|"利用する"| direct_map
direct_map -->|"軽減する"| memory_footprint
windows_sandbox -->|"で構成できる"| wsb_configuration_file
container_hyperv_isolation -->|"実装を担う"| security_boundary
container_process_isolation -->|"用いるのは非推奨"| untrusted_code_execution
container_hyperv_isolation -->|"推奨される対応"| untrusted_code_execution
wsl2 -.->|"前提とする"| nested_virtualization
container_hyperv_isolation -->|"利用する"| lightweight_utility_vm
direct_map -->|"前提とする"| dynamic_base_image
dynamic_base_image -->|"軽減する"| disk_footprint
container_hyperv_isolation -.->|"前提とする"| nested_virtualization
container_process_isolation -->|"利用する"| namespace_isolation
wsb_configuration_file -->|"推奨される対応"| untrusted_code_execution
same_os_file_placement -->|"推奨される対応"| cross_os_file_access
図の実線は常に成り立つ関係、破線は条件付きの関係です(成立条件は詳細ページの各関係の説明に記載)。関係すべての一覧(全19件、根拠・確度つき)と主要概念の定義は知識マップ詳細ページにまとめています。データ: JSON-LD / Turtle
2. フルVMは何を抱えているのか
比較の基準として、従来型のVMが抱えるものを整理しておきます。
- 独立したOSイメージ。 仮想ディスクの中にゲストOSの全ファイルを持ちます。ホストに同じWindowsがあっても共有はしません。
- 粗いメモリ割り当て。 従来型VMはホストメモリを静的なサイズで割り当てるのが基本です。Hyper-Vの動的メモリのように設定範囲内で割り当てを増減させる仕組みもありますが、需要の変化に応じた調整の手段は限られます。2
- 汎用のフルブート。 ファームウェア、ブートローダー、サービス群と、物理マシンと同じ手順で起動します。
flowchart TB
accTitle: フルVMが抱える3つの荷物
accDescr: フルVMは独立したOSイメージ、静的が基本のメモリ割り当て、汎用のフルブートを抱えており、それがディスク・RAM・起動時間のコストとして現れる
fullvm["フルVM"] --> b1["独立したOSイメージ"]
fullvm --> b2["静的が基本のメモリ割り当て"]
fullvm --> b3["汎用のフルブート"]
b1 -.-> c1["ディスクを複製分だけ消費"]
b2 -.-> c2["使わない分もRAMを抱えがち"]
b3 -.-> c3["起動に数十秒かかる"]
図2: フルVMのコストの内訳は、どれも隔離のためではなく汎用性と複製のために払っている。
これらは欠点ではなく、「ゲストに何でも入れられる」汎用性の代価です。Windows Serverの隣に古いLinuxを動かすような用途では、この汎用性こそが価値です。しかし「ホストと同じ(または決まった)OSを、開発・検証のために今すぐ動かしたい」という用途では、ほとんどが無駄な荷物になります。軽量VMは、用途を絞ることでこの荷物を下ろします。
3. WSL2 ── 用途特化カーネルを積んだユーティリティVM
3.1. 構造:管理されたVMと、その中のディストリビューション
WSL2は、軽量ユーティリティVMの中で本物のLinuxカーネルを動かす仕組みです。3 ポイントは3つあります。
- カーネルは本物、ただし特化品。 MicrosoftがStableブランチからビルドしたLinuxカーネルで、サイズと性能をWSL2向けに調整済み。現在の標準であるMicrosoft Store配布のWSLでは、カーネルはWSL本体のパッケージと一緒に更新され、
wsl --updateで適用できます(Windows組み込みの旧配布ではWindows Update経由でした)。4 本物のカーネルなのでシステムコール互換性は完全で、Dockerのようなツールもそのまま動きます。 - VMは裏方。 VMの作成・起動・停止はWSLが管理し、利用者はシェルを開くだけです。VM設定の画面も起動待ちの体感もありません。4
- ディストリビューションはVM内のコンテナー。 UbuntuやDebianなどの各ディストリビューションは、1つの管理されたVMの中で、隔離されたコンテナーとして動きます。ネットワーク名前空間やカーネルは共有しつつ、PID・マウント・ユーザーなどの名前空間は分離されています。3
flowchart TB
accTitle: WSL2のアーキテクチャ
accDescr: ハイパーバイザーの上にホストWindowsと軽量ユーティリティVMが並び、VMの中でMicrosoftビルドのLinuxカーネルが動き、各ディストリビューションはその中の隔離されたコンテナーとして動く
hv["ハイパーバイザー"] --> host["ホストWindows"]
hv --> uvm["軽量ユーティリティVM"]
uvm --> lk["Linuxカーネル(Microsoftビルド・wsl --updateで更新)"]
lk --> u1["Ubuntu(コンテナー)"]
lk --> u2["Debian(コンテナー)"]
host <-->|"相互運用(コマンド・ファイル・ネットワーク)"| uvm
図3: 「WSL2はVMか」の答えは「はい、ただし管理された黒子のVM」であり、ディストリビューションを複数入れてもVMは1つになる。
wslと打った瞬間の裏側は、こうなっています。
flowchart TB
accTitle: wslコマンド実行から数秒でシェルが返るまで
accDescr: wsl実行時にユーティリティVMが未起動なら軽量VMとLinuxカーネルを起動し、起動済みならそのまま使い、ディストリビューションのコンテナーでシェルが返る
cmd["wslを実行"] --> vmq{"ユーティリティVMは起動済み?"}
vmq -->|いいえ| bootvm["軽量VMとLinuxカーネルを起動(数秒)"]
vmq -->|はい| reuse["起動済みのVMをそのまま使う"]
bootvm --> shell["コンテナー内でシェルが返る"]
reuse --> shell
図4: 待ち時間の正体は最小限のVM起動だけで、フルブートの荷物を下ろした効果がここに出る。
3.2. ファイルI/O:どちら側に置くかで別物になる
WSL2の性能の話で必ず登場するのが、ファイルの置き場所です。
- Linux側(ext4の仮想ディスク)のファイルへの操作は高速です。Linuxカーネルが自前のファイルシステムを直接扱うためで、tarballの展開でWSL1比最大20倍、
git cloneやnpm installで2〜5倍の高速化が報告されています。4 - Windows側(/mnt/cなど)のファイルへの操作は、OSの境界を越えるファイル共有経由になるため遅くなります。OSファイルシステム間の性能は、WSL2がWSL1に劣る唯一の主要項目です。4
したがって原則は、「プロジェクトファイルは、それを操作するツールと同じOS側に置く」です。4 Linuxのビルドツールで扱うリポジトリはLinux側に、Visual StudioでビルドするソリューションはWindows側に置きます。
flowchart TB
accTitle: WSL2のファイルI/O経路の分岐
accDescr: Linux側のext4仮想ディスクへはLinuxカーネルが直接アクセスするため高速で、Windows側のファイルへはOS境界を越えるファイル共有経由になるため低速という分岐
io["WSL2内のファイル操作"] --> place{"ファイルはどちら側?"}
place -->|"Linux側(ホームなど)"| ext4["ext4仮想ディスクへ直接I/O"]
place -->|"Windows側(/mnt/cなど)"| p9["OS境界を越える共有経由"]
ext4 --> fast["高速(WSL1比で最大20倍の例)"]
p9 --> slow["低速になりやすい"]
slow -.-> fix["対策:ファイルを使う側のOSへ置く"]
図5: 遅いのはWSL2ではなく経路なので、置き場所を変えるだけで性能問題が消えることが多い。
3.3. メモリ:増えて、減って、でも返しきらない
WSL2のメモリ使用量(タスクマネージャーではvmmemプロセスとして見えます)は、固定予約ではなく使用に応じて増減します。プロセスが解放したメモリは、既定で有効なpageReporting設定の下でWindowsへ自動的に返却されます。5ファイルキャッシュとして保持されたページは、かつてはVMを終了するまでWindowsへ返りませんでした。4 現行のWSLでは、.wslconfigの実験的設定autoMemoryReclaim(既定はdropCache)がキャッシュも自動で回収します。5 この設定をdisabledにした環境や古いWSLでは、長時間セッションのキャッシュがVM終了まで残り、ホスト側のメモリを圧迫し得ます。
flowchart TB
accTitle: WSL2のメモリの増減と返却の流れ
accDescr: WSL2内の需要増でVMのメモリ使用量が増え、プロセスの解放分は既定で有効なpageReportingの下でWindowsへ返却され、ファイルキャッシュは既定でautoMemoryReclaimが自動回収するが、これらを無効にした設定や古いWSLではVM終了まで残り、wslのshutdownで全て返却される
grow["WSL2内でメモリ需要が増える"] --> vm["vmmemの使用量が増える"]
vm --> freed{"そのページは解放された?"}
freed -->|"プロセスが解放(pageReporting有効時)"| ret["Windowsへ自動返却"]
freed -->|ファイルキャッシュとして保持| amr["autoMemoryReclaimが自動回収(既定)"]
amr -.-> old2["無効設定や古いWSLではVM終了まで残る"]
old2 --> sd["wsl --shutdownで全て返却"]
図6: 「増えたきり」に見えるのは主にキャッシュの分(pageReporting無効時はプロセス解放分も残る)なので、リークと決めつける前に返却の経路を知っておく。
上限を明示したい場合は、%UserProfile%\.wslconfigでVM全体のメモリ・CPU数・スワップを制御できます。5
# %UserProfile%\.wslconfig
[wsl2]
memory=8GB
processors=4
swap=2GB
設定変更後はwsl --shutdownでVMを再起動すると反映されます。この「上限を決めるのは設定、実際の使用量は需要次第」という動的な配分が、次のWindows Sandboxではさらに徹底されます。
4. Windows Sandbox ── ホストのWindowsを「もう一度使う」
4.1. 動的ベースイメージ:500MBで完全なWindows
Windows Sandboxは、ハイパーバイザーで隔離された使い捨てのWindowsデスクトップです。閉じればすべて消え、次回はまっさらな状態で数秒で起動します。1
まず不思議なのはディスクです。完全なWindowsを起動できるのに、Sandboxのベースイメージはインストール後で約500MB、配布時は圧縮30MBしかありません。2 秘密は動的ベースイメージにあります。
- OSファイルの大半は不変(immutable)であり、ホストのものをそのまま共有できます。
- 可変(mutable)な少数のファイルだけは共有できないため、きれいなコピーをベースイメージ内に保持します。
- 起動時には、ホストの不変ファイル+手元の可変ファイルのコピーを組み合わせて、完全なWindowsイメージを構成します。2
つまりSandboxは、Windowsの複製をダウンロードも保存もせず、ホストにインストール済みのWindowsを再利用して起動しているのです。
flowchart TB
accTitle: 動的ベースイメージの構成
accDescr: ホストのWindowsのうち不変のOSファイルは共有し、可変ファイルだけきれいなコピーをベースイメージに持ち、両者を組み合わせてSandboxの完全なWindowsイメージを構成する
hostw["ホストのWindows一式"] --> imm["不変のOSファイル(大多数)"]
hostw --> mut["可変のOSファイル(少数)"]
imm -->|そのまま共有| img["Sandboxの起動イメージ"]
mut -->|きれいなコピーを保持| img
img --> boot["完全なWindowsとして起動"]
img -.-> size["保存が必要なのは約500MBのみ"]
図7: 「Windowsをもう1つ持つ」のではなく「ホストのWindowsから組み立てる」のが、ディスクの複製をやめた形である。
この構成だからこそ、次のライフサイクルが成り立ちます。なお、破棄されるのはSandbox内のローカルな状態です。.wsb構成ファイルで書き込み可能なフォルダーをホストからマップしている場合、そこへの変更はホスト側に残ります。6
flowchart TB
accTitle: Windows Sandboxのライフサイクル
accDescr: 起動するとまっさらなWindowsが数秒で用意され、アプリの検証や実験のあと閉じるとSandbox内の状態はすべて破棄されて次回もまっさらな状態から始まるが、書き込み可能でマップしたホスト側フォルダーへの変更は残る
launch["起動(数秒)"] --> clean["まっさらなWindows"]
clean --> work["アプリの検証や実験"]
work --> close2["閉じる"]
close2 --> discard["Sandbox内の状態をすべて破棄"]
discard -.-> mapped["マップした書き込み可能フォルダーの変更はホストに残る"]
discard -->|次回起動| launch
図8: 毎回まっさらに戻れるのは可変部分が使い捨てのコピーだからで、消すことが設計の一部になっている。
4.2. ダイレクトマップ:同じntdll.dllは同じ物理ページ
ディスクだけでなく、RAMも共有されます。Sandboxはホストと同じOSイメージを動かすため、OSバイナリについてはホストと同じ物理メモリページを使う「ダイレクトマップ」という技術が使われています。Sandbox内でntdll.dllがメモリへ読み込まれるとき、それはホストで読み込まれた同バイナリと同じ物理ページを指します。ホストの秘密を危険に晒すことなく、従来型VMよりずっと小さなメモリフットプリントを実現しています。2
「同じ物理ページを複数の利用者で共有する」──これはメモリ連載第3回で追った、セクションオブジェクトによるDLL共有(「セクションオブジェクトとコピーオンライト」)と同じ発想です。あの仕組みはプロセス間の共有でしたが、SandboxはVM境界をまたいでそれを行います。
flowchart TB
accTitle: ダイレクトマップによる物理ページ共有
accDescr: ホスト上のアプリとSandbox内のアプリが、ntdllなどのOSバイナリについて同一の物理メモリページを共有し、メモリ使用量を削減する
happ["ホストのアプリ"] --> hva["ホスト側の仮想アドレス"]
sapp["Sandbox内のアプリ"] --> sva["Sandbox側の仮想アドレス"]
hva --> phys["同一の物理ページ(ntdll.dllなどのOSバイナリ)"]
sva --> phys
phys -.-> save["OS分のRAM複製が不要になる"]
図9: プロセス間で使われてきたページ共有の発想を、VM境界をまたいで適用したのがダイレクトマップ。
4.3. メモリの貸し借り:VMというよりプロセスのように
従来型VMの静的なメモリ割り当てに対し、Sandboxの土台であるコンテナー技術は、ホストと協調してリソース配分を動的に決めます。ホストがメモリ不足になれば、通常のプロセスから回収するのと同じように、コンテナーからもメモリを回収できます。2 Hyper-Vの動的メモリも設定範囲内でVMへの割り当てを増減させますが、Sandboxはさらに進んで、ホストのメモリ管理と同じ土俵で融通し合う点が異なります。
flowchart TB
accTitle: ホストとSandboxのメモリの協調
accDescr: 従来型VMは静的なサイズの専有が基本で調整の手段が限られるのに対し、Sandboxはホストのメモリ圧力に応じて回収の対象になり、通常のプロセスと同じ土俵でメモリを融通し合う
pressure["ホストのメモリ圧力が高まる"] --> from{"どこから回収する?"}
from --> proc["通常のプロセスのWorking Set"]
from --> sbx["Sandbox(コンテナー)の使用分"]
proc --> relief["空きメモリを確保"]
sbx --> relief
relief -.-> contrast["従来型VMは調整の手段が限られる"]
図10: Sandboxはメモリの融通においてVMではなくプロセスの側に立ち、ホストが苦しいときは差し出す。
第1回で「VMの性能はホスト側にも依存する」と述べましたが、軽量VMではさらに一歩進んで、メモリの配分そのものがホストとの共同作業になっています。Sandboxが「重い仮想化ソフト」ではなく「もう1つのアプリ」くらいの感覚で使えるのは、この協調のおかげです。
なお、Sandboxを業務アプリの検証に使う具体的な手順は、既出の「Windows Sandboxで業務アプリ検証環境を作る」で扱っています。本記事はその足元の仕組み側です。
5. コンテナー ── 分離の線をどこに引くか
5.1. プロセス分離とHyper-V分離
Windowsコンテナーには、実行時の分離モードが2つあります。イメージは共通で、起動時のフラグで選べます。7
- プロセス分離:複数のコンテナーがホストとカーネルを共有し、ファイルシステム・レジストリ・ネットワークポート・プロセスID空間・オブジェクトマネージャー名前空間などの名前空間ごとの仮想化で分離します。Linuxコンテナーとほぼ同じ方式です。
- Hyper-V分離:各コンテナーが高度に最適化されたVMの中で動き、実質的に専用のカーネルを持ちます。VMの存在により、コンテナーどうしとホストの間にハードウェアレベルの分離が入ります。7
名前空間による分離は、レジストリ仮想化の記事(「Windowsのレジストリリダイレクトと仮想化」)で見た「同じAPIの下で別の実体を見せる」手法の徹底版と言えます。
flowchart TB
accTitle: プロセス分離とHyper-V分離の対比
accDescr: プロセス分離ではコンテナーがホストとカーネルを共有し名前空間で分離するのに対し、Hyper-V分離では各コンテナーが最適化されたVM内で専用カーネルを持つ
subgraph pi ["プロセス分離"]
c1["コンテナーA"] --> sk1["ホストと共有のカーネル"]
c2["コンテナーB"] --> sk1
end
subgraph hi ["Hyper-V分離"]
c3["コンテナーC"] --> k3["専用カーネル(最適化VM内)"]
c4["コンテナーD"] --> k4["専用カーネル(最適化VM内)"]
end
sk1 ~~~ c3
図11: 同じコンテナーイメージでも、分離の線をカーネルの上に引くか、カーネルごと分けるかは起動時に選べる。
5.2. 「セキュリティ境界」と呼べるのはどちらか
この2モードの違いは、性能の話に留まりません。Microsoftは、プロセス分離のコンテナーを堅牢なセキュリティ境界とは見なしていません。セキュリティ境界として保守(脆弱性対応)されるのはハイパーバイザー分離のコンテナーであり、敵対的なマルチテナントのシナリオではHyper-V分離を選ぶべきとされています。8
第2回で見たVBSも「カーネルは破られ得る」を前提にハイパーバイザー境界へ退避する設計でした。コンテナーの世界でも同じ判断基準が通用します。信頼できないコードを閉じ込める線は、カーネル共有の内側ではなく、ハイパーバイザーの境界に引く。
flowchart TB
accTitle: 実行するコードの信頼度と隔離の選び方
accDescr: 信頼できるワークロードならプロセス分離で密度と性能を取り、信頼できないコードや他者のコードならHyper-V分離コンテナーや、ネットワーク等を無効化した強化構成のWindows Sandbox、隔離されたVMなどハイパーバイザー境界を選ぶ
trust{"そのコードを信頼できる?"} -->|できる| dens["プロセス分離(密度と速度を優先)"]
trust -->|できない・他者のコード| bound["ハイパーバイザー境界を選ぶ"]
bound --> opt1["Hyper-V分離コンテナー"]
bound --> opt2["強化構成のSandboxや隔離VM"]
図12: 分離モードは性能の話である前にセキュリティの話であり、信頼度が線の引き場所を決める。
ちなみにHyper-V分離コンテナーをHyper-V VMの中で動かすと、ハイパーバイザーが二段になる入れ子の仮想化になります。1段の入れ子は、条件を満たす環境(IntelプロセッサはWindows 10/Windows Server 2016以降、AMDプロセッサはWindows 11/Windows Server 2022以降のホストと、それぞれ対応するVM構成バージョン)で本番でもサポートされており、加えて外側のVMへ仮想化支援機能を公開する設定(Hyper-VならSet-VMProcessorのExposeVirtualizationExtensions)が前提です。VM内でWSL2を動かす構成も同様にサポートされています。9 クラウド上の開発VMでWSL2やDockerを使えるかどうかも、そのVMサイズ・設定が入れ子の仮想化を公開しているかで決まります。
flowchart TB
accTitle: 入れ子の仮想化の構造
accDescr: 物理ホストのハイパーバイザーの上にクラウドVMがあり、その中でもう1段のハイパーバイザー(サポートされる入れ子は1段まで)が動いてWSL2やHyper-V分離コンテナーを支える
phys3["物理ホストのハイパーバイザー"] --> cvm["クラウドVM(開発マシン)"]
cvm --> nhv["VM内のハイパーバイザー(入れ子1段目)"]
nhv --> w2["WSL2"]
nhv --> hvc["Hyper-V分離コンテナー"]
nhv -.-> limit["サポートされる入れ子は1段まで"]
図13: クラウドVMの中でwslが動くのは、入れ子の仮想化が1段だけ公式に支えられているから。
5.3. 隔離と軽さのスペクトラム
ここまでの登場人物を1本の軸に並べると、次のようになります。
flowchart TB
accTitle: 分離の強さと軽さのスペクトラム
accDescr: プロセス分離コンテナーは最も軽いがカーネルを共有し、WSL2とSandboxとHyper-V分離コンテナーは専用カーネルを持つ軽量VM(Sandboxはホスト共有、WSL2は特化カーネルで軽量化)で、フルVMは最も重いが汎用という並び
ax["軽い ← → 重い"] ~~~ p1
p1["プロセス分離コンテナー(カーネル共有)"] --> p2["WSL2・Sandbox・Hyper-V分離(専用カーネルの軽量VM)"]
p2 --> p3["フルVM(何でも動く・複製を全部持つ)"]
p1 -.-> n1["境界:名前空間"]
p2 -.-> n2["境界:ハイパーバイザー"]
p3 -.-> n3["境界:ハイパーバイザー+完全な独立"]
図14: 軽量VM群はハイパーバイザー境界を保ったまま複製を削った中間解で、削り方はSandboxが共有、WSL2が特化カーネルと分かれる。
6. 自分の目で確かめる
軽さと共有は、手元で観測できます。
起動時間とメモリの増減(WSL2)。 タスクマネージャーを開いたまま、次を実行してみてください。
# 起動時間の体感(初回はVM起動、2回目以降はさらに速い)
Measure-Command { wsl -e true }
# WSL2のVMのメモリ使用量(vmmem / Virtual Machine Memory)
Get-Process -Name vmmem* | Select-Object Name, WorkingSet64
# VMごと終了してメモリが返る様子を見る
wsl --shutdown
WSL2内で大きなビルドやファイル操作をするとvmmemが育ち、wsl --shutdownで一気に返却されるのが観測できます。
ファイル置き場所による速度差(WSL2)。 同じリポジトリをLinux側(~/repo)とWindows側(/mnt/c/repo)へ置き、git statusや展開処理の時間を比べると、第3.2節の差が数字で見えます。
ダイレクトマップの前提知識(Sandbox)。 Sandboxを起動し、ホストのタスクマネージャーでメモリの増分を見てください。「Windowsがもう1つ」から想像されるよりずっと小さい増分で収まることが、共有の効果を物語ります。ホスト側のメモリ内訳をさらに掘るには、RAMMapやVMMapの使い方をまとめたSysinternalsツールの記事(「Process Explorer・Handle・VMMapの使い方」)が参考になります。ただしこれらはホスト側のプロセスや物理メモリの分類を見る道具で、ゲストとの共有そのものを直接観測するわけではありません。
コンテナーの分離モード(Docker/Windowsコンテナー)。 Windowsコンテナー環境があるなら、docker run --isolation=processと--isolation=hypervで同じイメージを起動し、起動時間とタスクマネージャーの見え方(プロセス分離ではコンテナー内プロセスがホストのプロセス一覧に見える)を比べると、分離の線の位置が体感できます。7 ただしプロセス分離はホストとイメージのバージョン一致が前提で、クライアントOS上では開発・テスト用途に限られます。Hyper-V分離はより広い組み合わせを許容するため、比較は互換な組み合わせで行ってください。10
7. 実務で避けたい3つの誤読
7.1. 「WSL2は遅い」
遅いのはWSL2ではなく、OS境界をまたぐファイルI/Oの経路です。プロジェクトをLinux側へ移すだけで、体感が別物になるケースが多くあります。4 逆に、Windowsのツールから触るファイルをLinux側へ置くのも同じ理由で不利です。「使う側と同じOSに置く」で判断してください。
7.2. 「vmmemが肥大するのはメモリリーク」
WSL2のメモリは需要に応じて増減し、解放分は返却されます。現行のWSLなら、ファイルキャッシュもautoMemoryReclaim(既定はdropCache)が自動で回収するため、「大きくなったまま」は時間とともに解消されることが多いです。5 それでも残る場合は、autoMemoryReclaimがdisabledになっていないか、解放分の返却を担うpageReportingが無効化されていないか(または古いWSLでないか)を確認したうえで、.wslconfigのmemoryで上限を明示するか、セッションの区切りにwsl --shutdownで全て返却します。リークかどうかの切り分けの考え方は、メモリ連載の導入編「Windowsの『メモリ使用量』は何を表しているのか」と同じです。
7.3. 「コンテナーに入れたから安全」
プロセス分離のコンテナーはカーネルを共有しており、Microsoftの基準ではセキュリティ境界ではありません。8 信頼できないコードや検体の実行には、Hyper-V分離のコンテナー、Windows Sandbox、または専用VMのように、ハイパーバイザー境界を持つ隔離を選んでください。ただし、ハイパーバイザー境界は万能の免罪符ではありません。Windows Sandboxの既定設定ではネットワーク接続が有効で、信頼できないアプリを内部ネットワークに晒し得ます。1 検体の実行に使うなら、.wsb構成ファイルでネットワークやクリップボードのリダイレクトを無効化して分離を強めるか、隔離されたネットワーク上の専用VMを使ってください。
8. まとめ ── 連載を締めくくる
第3回の要点です。
- 軽量VMの軽さは「隔離を弱めた」結果ではなく「複製をやめた」結果です。
- WSL2は管理された軽量ユーティリティVMで本物のLinuxカーネルを動かし、ディストリビューションはVM内のコンテナーとして分離されます。3 ファイルは使う側のOSに置くのが性能の原則で、メモリは動的に増減し
.wslconfigで上限を制御できます。45 - Windows Sandboxは、動的ベースイメージでホストの不変OSファイルを共有し、ダイレクトマップで対象OSバイナリの物理ページも共有することで、Windows一式の複製を持ちません。2 可変ファイルの約500MBと、中で動かすアプリ自身のメモリは別に必要です。
- コンテナーの分離モードは起動時に選べ、セキュリティ境界と呼べるのはHyper-V分離の側です。78
そして連載全体を1枚にまとめると、こうなります。
- 第1回:Windowsの下にはハイパーバイザーの層があり、ホストOS自身がルートパーティションとして動く。CPUとメモリ(SLAT)の調停はこの層が直接行い、合成デバイスのI/OはVMBusの先でルートパーティション(VSP)が仲介する。
- 第2回:その層はVMどうしの分離だけでなく、同じOSの内側にカーネルより強い境界(VTL)を引くためにも使われる。Windows 11の既定のセキュリティは、この上に建っている。
- 第3回:同じ層の上で、複製を削ることで「数秒で起動する仮想マシン」が成立する。隔離の線は保たれたまま、日常の道具になった。
flowchart TB
accTitle: 連載全体の一枚絵
accDescr: ハードウェア直上のハイパーバイザーが第1回、ホストWindows内のVTL0とVTL1の分離が第2回、同じ層に載るWSL2・Sandbox・Hyper-V分離の軽さが第3回に対応し、プロセス分離コンテナーはホストのカーネルを共有し、Sandboxは共有で、WSL2は特化カーネルで軽くなる
hw3["ハードウェア"] --> hv3["ハイパーバイザー(第1回)"]
hv3 --> rp3["ホストWindows(VTL分離は第2回)"]
hv3 --> lw3["WSL2・Sandbox・Hyper-V分離(第3回)"]
rp3 --> pc3["プロセス分離コンテナー(カーネル共有)"]
lw3 -.-> mech3["Sandboxは共有・WSL2は特化カーネルで軽量化"]
図15: 3回分を積み上げると、現在のWindowsの足元の全体像になる。
仮想化はもはや、サーバー室の技術でも、VMを立てる人だけの技術でもありません。あなたのWindowsの足元で、セキュリティと開発体験の両方を静かに支えている──それが現在地です。
関連記事
- Windows仮想化の深層(第1回) ── あなたのWindowsはどこで動いているのか:ハイパーバイザーとパーティション
- Windows仮想化の深層(第2回) ── カーネルからも見えないメモリ:VBS・HVCI・Credential Guardの仕組み
- Windowsメモリの深層(第3回) ── セクションオブジェクトとコピーオンライト
- Windows Sandboxで業務アプリ検証環境を作る
- Windowsのレジストリリダイレクトと仮想化
関連する相談領域
合同会社小村ソフトでは、WSL2やコンテナーを使った開発環境の整備、Windowsアプリの検証環境設計、仮想化環境での性能・互換性調査を扱っています。
参考リンク
-
Microsoft Learn, Windows Sandbox. Windows Sandboxが使い捨てのVMとして数秒で起動し、閉じるとすべて破棄されること、Microsoftハイパーバイザーで別カーネルを動かしてホストから分離すること、および既定でネットワーク接続が有効であり構成ファイルで無効化できることについて。 ↩ ↩2 ↩3
-
Microsoft Learn, Windows Sandbox architecture. 動的ベースイメージがホストの不変OSファイルの共有と可変ファイルのきれいなコピーで完全なWindowsイメージを構成すること(インストール後約500MB)、従来型VMの静的メモリ割り当てに対しコンテナーはホストと協調して動的に配分しホストがメモリを回収できること、ダイレクトマップによりntdll.dllなどのOSバイナリがホストと同じ物理ページを使うことについて。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, What is the Windows Subsystem for Linux?. WSL2が軽量ユーティリティVMの中でLinuxカーネルを動かすこと、各ディストリビューションが隔離されたコンテナーとして動き、ネットワーク名前空間やカーネルを共有しつつPID・マウント・ユーザーなどの名前空間を分離することについて。 ↩ ↩2 ↩3
-
Microsoft Learn, Comparing WSL Versions. WSL2のカーネルがMicrosoftによりStableブランチからビルドされること、Store配布のWSLは更新をOSイメージから切り離してパッケージとして受け取り
wsl --updateで適用できること(Windows組み込みの旧配布ではWindows Update経由)、tarball展開で最大20倍などの性能例、OSファイルシステム間の性能ではWSL1が上回るためファイルを使う側のOSへ置くべきこと、メモリが増減し解放分は返却されるがキャッシュはVM終了まで返らない場合があることについて。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 -
Microsoft Learn, Advanced settings configuration in WSL. .wslconfigの[wsl2]セクションでWSL2のVM全体のメモリ上限・プロセッサ数・スワップやpageReporting(既定で有効。未使用メモリの検出と返却を担う)を設定できること、および実験的設定autoMemoryReclaimの既定値がdropCacheで、キャッシュメモリが自動的に回収されることについて。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Use and configure Windows Sandbox. .wsb構成ファイルのMappedFoldersでホストのフォルダーを読み取り専用または書き込み可能で共有できることについて。 ↩
-
Microsoft Learn, Isolation Modes. Windowsコンテナーのプロセス分離がホストとカーネルを共有し名前空間で分離すること、Hyper-V分離が最適化されたVM内で実質的に専用カーネルを持つこと、同じイメージを起動時のフラグでどちらのモードでも実行できることについて。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Secure Windows containers. ハイパーバイザー分離のコンテナーのみがセキュリティ境界とされ、プロセス分離のコンテナーは堅牢なセキュリティ境界と見なされないこと、敵対的マルチテナントではハイパーバイザー分離を選ぶべきことについて。 ↩ ↩2 ↩3
-
Microsoft Learn, What is Nested Virtualization?. Hyper-V VM内でのHyper-V分離コンテナーの実行(1段の入れ子)が本番でサポートされること、要件としてIntelプロセッサはWindows Server 2016/Windows 10以降、AMDプロセッサはWindows Server 2022/Windows 11以降のホストとそれぞれ対応するVM構成バージョンが必要なこと、外側のVMへ仮想化支援機能を公開する設定(ExposeVirtualizationExtensions)が前提条件であること、Hyper-V VM内でのWSL2の実行がサポートされることについて。 ↩
-
Microsoft Learn, Windows container version compatibility. プロセス分離がホストとコンテナーイメージのバージョン一致を前提とすること、Hyper-V分離ならホストと異なるOSバージョンのイメージを実行できること、クライアントOSでのプロセス分離が開発・テスト用途に限られることについて。 ↩
関連する記事
同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。
Windows仮想化の深層(第1回) ── あなたのWindowsはどこで動いているのか:ハイパーバイザーとパーティション
Hyper-Vを有効にするとホストのWindows自体がルートパーティションとしてハイパーバイザーの上で動きます。VT-x、SLAT、VMBusの役割まで、仮想化の土台を解説します。
Windows仮想化の深層(第2回) ── カーネルからも見えないメモリ:VBS・HVCI・Credential Guardの仕組み
対応ハードウェアへのクリーンインストールで既定有効になるVBSは、ハイパーバイザーとSLATでカーネルより強い隔離を作ります。VTL、セキュアカーネル、HVCI、Credential Guardの構造を解説します。
Windows Sandboxでアプリ検証を速くする方法
Windows Sandbox を使って、管理者権限の問題の切り分け、クリーン環境での再現、権限不足・リソース不足の再現を効率化する方法を、.wsb と CLI の使い分けまで含めて整理します。
Win32スレッドプールAPI ── CreateThreadpoolWorkで「スレッドを作らない」並行処理
ネイティブコードでCreateThreadを乱立させていませんか。Vistaで刷新されたWin32スレッドプールAPIのwork・timer・wait・ioの4オブジェクト、クリーンアップグループ、コールバックでの禁止事項までを一次情報にもとづいて解説します。
名前付きパイプの実務 ── Windowsプロセス間通信の定番を設計からセキュリティまで
Windowsのプロセス間通信の定番・名前付きパイプを実務目線で解説します。バイト/メッセージモードの選択、複数クライアントを捌くサーバー設計、ACLと偽装のセキュリティ、.NETのNamedPipeStreamまで、一次情報にもとづき整理します。
関連トピック
このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。
Windows技術トピック
Windows 開発、不具合調査、既存資産活用の技術トピックをまとめた入口です。
このテーマがつながるサービス
この記事は次のサービスページにつながります。近い入口からご覧ください。
Windowsアプリ開発
業務アプリ、装置連携、通信ツールなどの Windows ソフト開発を支援します。
よくある質問
この記事のテーマについて、相談時によくある質問をまとめています。
- WSL2はVMなのですか?
- はい。WSL2は軽量ユーティリティVMの中で、Microsoftがビルドした本物のLinuxカーネルを動かします。ただしVMの管理はWSLが裏側で行うため、利用者にVMの設定や起動待ちを意識させない設計になっています。各Linuxディストリビューションはこの管理されたVMの中で隔離されたコンテナーとして動きます。
- WSL2で/mnt/c配下のファイル操作が遅いのはなぜですか?
- WSL2のLinuxカーネルからWindows側のファイルシステムへのアクセスは、OSの境界を越えるファイル共有経由になるためです。Linuxファイルシステム(ext4の仮想ディスク)上の操作は高速なので、プロジェクトファイルは作業するツールと同じOS側に置くのが原則です。
- vmmemプロセスのメモリ使用量が大きいのはリークですか?
- 多くの場合リークではありません。WSL2のメモリは使用に応じて増減し、プロセスが解放したメモリは既定で有効なpageReporting設定の下でWindowsへ返されます。ファイルキャッシュ分も、現行のWSLでは.wslconfigのautoMemoryReclaim(既定dropCache)が自動で回収します。これらの設定を無効にした環境や古いWSLではVM終了まで残ることがあり、その場合はmemory設定で上限を定めるか、wsl --shutdownで返却します。
- Windows Sandboxはどうして数百MBのディスクで完全なWindowsを起動できるのですか?
- 動的ベースイメージという仕組みで、ホストにインストール済みのWindowsのうち不変のOSファイルを共有し、可変の少数のファイルだけきれいなコピーを保持するためです。これにより、Windowsの複製を丸ごと保存せずに起動可能な完全イメージを構成しています。
- コンテナーはVMより安全なのですか?
- 分離モードによります。プロセス分離のコンテナーはホストとカーネルを共有し、Microsoftはこれを堅牢なセキュリティ境界とは見なしていません。敵対的なコードを扱う場合は、コンテナーごとに専用カーネルを持つHyper-V分離を選ぶ必要があります。