2020年春に提供予定の機能アップデート「20H1」のプレビュー版に、WSLを強化した「WSL 2」が実装された。早速、WSL 2でどのような変更があるのか、Linuxとの互換性は向上しているのかなどを簡単に検証してみた。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
2020年春に提供予定の機能アップデート「20H1」のプレビュー版「Windows Insider Preview Build 18917」の提供がFast Ring(更新頻度が高く、新しい機能を早く試せるリリース)に設定しているユーザー向けに配布が開始された。このBuild 18917から、新しい機能としてWindows Subsystem for Linux (WSL)を強化した「WSL 2」のプレビューが含まれている(WSL 2については、Windows 10 The Latest「完全なLinuxがWindows 10上で稼働する? 『WSL 2』とは」参照のこと)。
本稿では、Windows Insider Preview Build 18922でWSL 2を動かしてみた結果を報告する。なお、WSL 2はプレビュー中であるため、最終的な仕様や性能などが変更される可能性のあることをお断りしておく。まず、このプレビュー版のファーストインプレッションをお届けする。
WSL 2は、Build 18917以降で利用可能だが、インストール前にあらかじめ現行のWSL(以下、区別のためにWSL 1と表記する)を有効にしておく必要がある。その上で、PowerShellのコマンドレットで有効にする必要がある。また、すでにインストールされているディストリビューションをWSL 2用に変換するか、設定を行った上で新規にディストリビューションをインストールする必要もある。
WSL 1が有効であれば、以下のコマンドレットをPowerShellで実行することで、WSL 2が有効になる。この際、PowerShellは管理者権限で起動しておく必要がある。
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
その後、すでにインストールされているWSLディストリビューションがあるならば、以下のコマンドレットで、WSL 2用に変換を行う(ここではUbuntu 18.04を仮定)。これによりインストールされているディストリビューションがWSL 2で動作するようになる。
wsl --set-version Ubuntu-18.04 2
以後は、WSL 1と同じく、wsl.exeやbash.exe、ubuntu1804.exeなどでWSL 2上のUbuntu 18.04を起動できる。
WSL 2の実装に伴い、wsl.exeコマンドのオプションも拡張されている。拡張されたのは主にWSL 2に関係するものだ。
オプション | オプション(省略型) | 動作 | October 2018 Updateまでのオプション | May 2019 Updateで実装されたオプション | WSL 2で実装されたオプション |
---|---|---|---|---|---|
--exec | -e <Cmd> | コマンド<Cmd>をWSL側で実行 | ○ | − | − |
-- <ARG> | 以後の引数<ARG>をWSL側に渡す | ○ | − | − | |
--distribution | -d <DIST> | 対象ディストリビューションの指定 | ○ | − | − |
--user | -u <USER> | WSL側ユーザーを指定 | ○ | − | − |
--export <DIST> <FILE> | 指定したディストリビューション<DIST>をtarファイル<FILE>にエクスポート | − | ○ | − | |
--import <DIST> <PATH> <FILE> | tarファイル<FILE>から指定したパス<PATH>へ<DIST>をインポート | − | ○ | − | |
--import <DIST> <PATH> <FILE> --version <VER> | 同 WSLバージョン指定<VER>付き | − | − | ○ | |
--list | -l | インストールされているディストリビューションを表示 | − | ○ | − |
--list --all | -l --all | インストールされているディストリビューション(unregister中を含む)を表示 | − | ○ | − |
--list --quiet | -l -q | インストールされているディストリビューション名だけ表示 | − | − | ○ |
--list --verbose | -l -v | インストールされているディストリビューションを詳細情報付きで表示 | − | − | ○ |
--list --running | -l --running | 起動しているディストリビューションを表示 | − | ○ | − |
--set-default | -s <DIST> | 既定のディストリビューションを<DIST>に指定 | − | ○ | − |
--set-default-version <VER> | 既定のディストリビューションを指定。WSLバージョンを<VER>に指定 | − | − | ○ | |
--set-version <DIST> <VER> | ディストリビューション<DIST>のWSLバージョンを<VER>に変換 | − | − | ○ | |
--shutdown | 起動中の全てのWSLを強制終了 | − | − | ○ | |
--terminate | -t <DIST> | 指定したディストリビューション<DIST>を終了 | − | ○ | − |
--unregister <DIST> | 指定したディストリビューション<DIST>を未登録(unregister)とする | − | ○ | − | |
--help | wsl.exeのヘルプを表示 | ○ | − | − | |
wsl.exeコマンドのオプション |
インストールされているWSLディストリビューションがWSL 1用かWSL 2用なのかを判断するには、オプションとして「-l -v」を指定すればよい(これらは「--List」オプションと「--verbose」オプションの省略形)。
既存のWSL 1用ディストリビューションをWSL 2用に変換するには、前述のように「--set-version」オプションを用いる。一方、新規にインストールするWSL用ディストリビューションをWSL 1とWSL 2のどちらで利用するのかは、「--set-default-version」オプションで指定する。
ディストリビューションは、Microsoft Storeからインストールするため、1つのディストリビューションは1つだけしかインストールできない。このため、ディストリビューションは、WSL 1かWSL 2のどちらかでしか動作できない点に注意が必要だ。同名のディストリビューションをWSL 1とWSL 2で同時には起動できないようになっている。
これにより、Windows 10 May 2019 Update(バージョン1903)から実装された、9PによるVolFs(WSL側ファイルシステムへのアクセス)は、1つのWSL$ホストを介して、1つだけのディストリビューションにアクセスするため、従来と矛盾を生じることはない(「9P」と「VolFs」については前出の解説記事を参照)。
物理メモリ8GBのPCで、WSL 2でUbuntu 18.04を起動すると、メモリは6GB程度割り当てられている。WSL 1では、ホスト側とほぼ同じメモリが物理メモリとして見えていたのと比べるとやや少ない。
また、スワップ領域は設定されておらず、仮想メモリは有効なものの、スワップなしで動作しているように見える。Linuxから見える物理メモリ(実際にはホスト側の仮想記憶)が6GB程度あれば、ある程度のアプリケーションは動作させることは可能だ。なお、WSL 1では、この辺りの情報を表示するvmstatコマンドが正しく動作していなかった。
Linuxのスワップに関してはパーティションの他、ファイルをスワップ領域とすることもできるのだが、この辺りの設定(swapon/swapoffコマンド)などがWSL 2で動作するのかも興味深いところだ(この辺りの機能については、今後検証していくつもりだ)。とはいえ、Microsoftがデフォルトでスワップをオフにしているのは、パフォーマンス関係でスワップが足かせになると判断している可能性も否定できない。
WSL 2最大のメリットは、本来のLinuxカーネルを利用するため、フルのLinuxになっている点だ。WSL 1では、Linuxカーネルは存在せず、WSL 2側のモジュールやデバイスが、Linuxカーネルのファンクションコールを、Windowsの機能に変換していた。このため、Linuxカーネルが提供する全機能のうち、一部は利用できなかった。例えば、前述のようにWSL 1では仮想記憶の情報を表示するvmstatコマンドが動作しなかった。また、標準で動作しているデバイスにも違いがあり、そういった点で動作しないプログラムもあった。
WSL 1で動かなかった有名な機能の1つにFUSE(Filesystem in Userspace:ユーザー空間で独自のファイルシステムを作成する仕組み)がある。FUSEは、/dev/fuseというデバイスを介して機能を利用するが、WSL 1では/dev/fuseデバイスはサポートされておらず存在しなかった。このため、FUSE関連機能は全て利用できなかった。
WSL 2では、標準のLinuxとほぼ同等(カーネルのコンフィギュレーションで組み込まれるデバイスドライバによりディストリビューションごとに違いはある)のデバイスが利用できる。
では実際にFUSEを使うsshfsという機能(SSH接続を利用して接続先のマシンのディレクトリをマウントする機能)を使ってみる。sshfsのインストールや設定使い方を説明するのは本記事の本筋ではないので省略するが、WSL 2ではFUSEを使うsshfsを動作させることができた。一方、WSL 1ではsshfsのインストールは可能なものの、やはり動作できなかった。
WSL 2では、ネイティブのファイルシステムであるext4が利用できる。このext4ファイルシステムは、Hyper-Vの仮想ハードディスクで実現されており、実体は、以下のパスにある。
%LocalAppData%¥Package¥<WSLディストリビューションパッケージ名>¥LocalState¥ext4.vhdx
[Package]フォルダ以下には、いやに長いファイル名があるが、ディストリビューション名などが一部に含まれているので判別は容易だろう。例えば、Ubuntu 18.04は、[CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc]フォルダが対応している。
ext4.vhdxは、通常のVHDXファイルであるため、diskpartコマンドにより情報を取得したり、領域を拡大したりできる。VHDXファイルは、書き込みが行われているセクターのみを保持し、未使用のセクターは保存しない。このため、初期状態では作成時に指定された容量に比べてファイルは小さい(1GB弱)。
ただし、一回書き込むと中のファイルを削除しても、vhdxファイル自体は短くならない。調べたところ、WSL 2のVHDXファイルは、最大256GBとして作成されているため、通常は、あまり拡大を行う必要はなさそうだ。また、diskpartで仮想ハードディスクの容量を拡大したあと、WSL 2側でファイルシステムを拡大する作業を行う必要がある。
WSL 1では、NTFS上のフォルダ構造をLinux側の仮想ファイルシステム(VFS)を介してアクセスするVolFsと呼ばれるファイルシステムが使われていた。これは、実体としてはNTFSであるため、ext4と比べるとその振る舞いに違いがあった。
例えば、VolFsではプログラムが開いているファイルなどの名前を変更できないが、ext4では、プロセスにより開かれているファイルであってもリネームが可能だ。こうした挙動の違いは、アプリケーションに対する非互換性になっていた。
ext4を使うことで、WSL 2は、WSL 1よりも高速なファイルアクセスが可能になるという。findコマンドでext4、VolFs上のファイルに対して特定の文字で始まるファイルを探してみた。実行時間の測定には、bash組み込みコマンドのtimeを使っている(スクロールをリダイレクトしているのはコンソールへの出力時間を抑制するため)。
time find /bin /lib /usr -name 'c*' >/dev/null
やはりWSL 2のほうが高速な結果を得られた。具体的には、findによるファイル名検索で約10倍の速度差があった。WSL 2では下画面のように数10ミリ秒程度であるのに対して、WSL 1では、数100ミリ秒程度になっている。
なお、Win32側のファイルをアクセスするためのDrvFsは、新たに9P(Plan 9 Filesystem Protocol)を使うものに変更になっている。これらを含め、mountコマンドの結果(現在のマウント状態)にも違いがある。
WSL 2では、Hyper-Vの仮想イーサネットアダプター(仮想ネットワークアダプター)を使ってホスト側と同じネットワークアダプターをWSL 2側に提供している。しかし、このためにWSL 2は、いったん仮想内部ネットワークに接続し、ホスト側に相当する仮想ネットワークアダプターを経由してLANやインターネットに接続することになる。
つまりWSL 2は、Win32側から見ると実ネットワークとは異なるネットワークアドレスを持つ仮想内部ネットワークに接続しているように見える。一方、WSL 2からWin32側は、仮想内部ネットワークに接続しているノードのように見えてしまう。このため、Win32とWSL 2は、異なるIPアドレスを持つだけでなく、WSL 2からWin32側をアクセスする場合には、Win32側は仮想内部ネットワーク側のIPアドレスでアクセスする必要がある。
WSL 1では、Win32側とネットワークを共有していたため、同じIPアドレスを持ち、LocalhostでWin32側へのアクセスができた。この辺り、現時点では、WSL 1とWSL 2の非互換となっている。Microsoftは、「これは一時的なもので、修正する優先順位リストの中で非常に高いもの」として対策中であるということだ。
ただ、Linuxカーネル内のTCP/IPスタックをそのまま使うとするとさすがにWindows OS側と同じIPアドレスというわけにもいかない。LinuxのTCP/IPスタックを使うか、WSL 1と同じくWindows OS側のものを使うかは、大きな違いがある。このあたりどうするのかは興味深いところだ。
WSL 2では、フル機能のLinuxであること、いわゆる仮想環境と比べると起動が速く、低いシステム負荷で利用できるというのがメリットだ。また、デュアルブートも不要で瞬時にLinuxが利用できるというのは、オリジナルのLinuxにないメリットである。
WSL 1に比べてもLinuxとしての互換性が高まっており、ほぼ普通のLinuxとして利用可能だ。今回は、プレビュー版だったが、特に動作中に落ちるということもなく、比較的完成度は高いと感じた。いま、ある程度WSLを使っていたり、普段Linuxを使う機会が多かったりするようならば、正式配布が開始されたら、取りあえず試してみることをお勧めする。
Copyright© Digital Advantage Corp. All Rights Reserved.