• Windows Subsystem for Linuxガイド 第11回 WSL2の設定.wslconfig

WSL2環境で利用する最大メモリやCPUコア数などの設定は、Win32側のユーザーフォルダーにある“.wslconfig”ファイルで行う。この設定は、WSLのVer.2環境で動作しているすべてのWSLディストリビューションに有効な設定となる。

なお、今回から、Windows 11の検証は、Ver.22H2をベースとしている。Microsoftストアから入手可能なWSLプレビュー版は、Windowsに付属するWSLとはパスなどが異なるので注意してほしい。

.wslconfigの概要

“.wslconfig”ファイル(先頭がピリオドで始まっていることに注意)は、ユーザーフォルダーに置かれている。標準では、ファイルは存在せず、すべての設定はデフォルト値になっている。指定可能な項目は、(表01)のようなものになる。WSLディストリビューション側の/etc/wsl.confと同じく、ファイルは、ini形式を模したもので、角括弧で挟まれた「セクション名」とセクションに属する「設定」行から構成される。現時点では、セクション名には“[wsl2]”しか存在しない。設定行は、「キー = 値」の形式を取る。また、“#”で始まる行は注釈となり意味を持たない。(リスト01)にサンプルの.wslconfigファイルを示す。

  • ■表01

■リスト01

# この行は注釈です [wsl2] memory=2GB pageReporting=true swap=2GB swapFIle=C:\\temp\\swapfile.vhdx processors=2 nestedVirtualization=false kernelCommandLine=mitigations=off kernel=C:\\temp\\kernel localhostForwarding=false guiApplications=false debugConsole=true vmIdleTimeout=1000

.wslconfigファイルを編集したあと、設定を有効にするには、WSLディストリビューションだけでなくWSL2自体をいったん終了させる必要がある。それには、WSLディストリビューションを終了させたあと、“wsl.exe --shutdown”でWSL2を終了させる。最後のWSLディストリビューションが終了したあと、一定時間が経過すると、WSL2仮想マシンは自動終了する。Windows 11では、その時間も.wslconfigで指定できる(後述)。ただし、コマンドからは、WSL2仮想マシンが終了したかどうかを確認することはできないため、.wslconfigの修正後は、前記コマンドで確実にWSL2仮想マシンを確実に終了させる。

メモリ関連

WSL2仮想マシンに割り当てる最大メモリサイズは、.wslconfの“memory”キーで行う。このときの値は、「サイズ値」と呼ばれる形式で、整数値の後ろにメモリの割当単位である「GB」(ギガバイト)、「MB」(メガバイト)などをつける。

デフォルト値は、Windows 11では「物理メモリの50%または8ギガバイトのどちらか小さい方」とされている。しかし、Windows 11 Ver.22H2で64ギガバイトを実装したマシンでデフォルト値の場合に32ギガバイト(つまり物理メモリの50%)が確保された。すべての場合に確認したわけではないが、Windows 11では、「物理メモリの50%」と考えていいようだ。

なお、WSL2仮想マシンへのメモリ割り当ては、「動的メモリ割り当て」が使われるため、物理メモリは利用時に割り当てが行われる。つまり、この値は、WSL2仮想マシンへの最大メモリ割り当てを指定するものだ。

WSL2仮想マシンへのメモリ割り当ては、すべてのWSLディストリビューションで共有する。複数のWSLディストリビューションが起動している場合、1つのディストリビューションがメモリを使うと、その分、他のディストリビューションでも空きメモリ領域が減ってしまう。複数のディストリビューションを起動しても、それぞれが大量のメモリを確保することはないが、起動しているディストリビューション間でメモリを分け合う状態になる。メモリ効率を考えると複数のディストリビューションを起動することにはデメリットが大きく、可能なら単独のディストリビューションに集約させたほうがよい。これは、後述のswap領域にも当てはまる。

なお、Linux側でメモリ量を調べるには、freeコマンドを使う(写真01)。具体的には、“free -h -t”のようにする。オプションは、単位を付けたメモリ量表記(-h)と、swapとの合計表示(-t)を指定している。オプションの詳細は、freeコマンドのmanページで調べていただきたい(以後のコマンドも同様)。なお、このコマンドは、スワップ領域のサイズを調べることにも利用できる。なお詳細なメモリに関する情報は、“/proc/meminfo”で読み出すこともできる。

  • 写真01: freeコマンドを使うとLinuxの管理しているメモリやswapのサイズを表示できる

このパラメーターは、後述のメモリ回収を行う前提であれば、デフォルトのままで問題ない。

メモリ回収の設定

一般的なLinuxカーネルは、メモリの空き領域をファイルキャッシュとして利用する。このため、空きメモリ領域があれば、それをファイルキャッシュとして確保してしまう。しかし、WSL2では、仮想マシン内で動作し、動的メモリ割り当てが行われるため、空きメモリは、Win32側にもどすことで、Windows全体としてのパフォーマンスを低下させないようにしている。

WSL2に使われるLinuxカーネルには、そのための仕組みがあり、アイドル時に、メモリコンパクション処理を行い、空いたメモリをWin32側に戻すことができる。これを制御するのが、.wslconfigのp“ageReporting”である。true(有効)またはfalse(無効)の論理値を指定する。

メモリの利用状態は、Win32側でタスクマネージャーやパフォーマンスモニターなどを使うことで簡易ではあるが確認することができる。(写真02)は、pageReportingが有効な場合のvmmmemWSL(WSL2仮想マシンのメモリ割り当てを行うホスト側プロセス)のメモリ割り当て状態である。Ubuntuディストリビューションで、stress(aptコマンドでインストール)を使ってメモリを確保させ、その後、stressを停止させた。プロセスのメモリ割り当て(Working set値)が段階的に下がって行くのがわかる。その後、Ubuntuセッションを終了すると起動前の状態に戻る。

  • 写真02: pageReportingが有効(=true)な場合、WSL2で確保したメモリは空きメモリになった段階で回収される

これに対して(写真03)は、pageReportingをfalseとしたときのもの。同じくstressでメモリを確保させたのちプロセスを停止させても、Working set値は戻らない。Ubuntuセッションを停止し、WSL2をシャットダウンするとメモリが解放される。

  • 写真03: pageReportingが無効(=false)な場合、WSL2で確保したメモリは、WSL2仮想マシンが終了するまで確保されたままになる

なお、Linux側で利用されているファイルキャッシュは、前述のfreeコマンドで、“buff/cache”として表示される。

基本的には、このパラメーターに関しては、特に理由がない限りtureのまま使う。

スワップの設定

Linuxでは仮想メモリを利用でき、そのときに使う外部記憶領域をswapと呼ぶ。Linuxではブロックデバイスやパーティション、ファイルなどにswap領域をおくことができる。WSL2では、専用のブロックデバイスが割り当てられているが、これは、Win32側の仮想ハードディスクファイル(VHDXファイル)である。

Linux側から見えるswap領域のサイズは、.wslconfigでは、swapキーと「サイズ値」で設定を行う。たとえば、4ギガバイトのスワップ領域を指定する場合“swap=4GB”とする。デフォルト値は、メモリ割り当て値(.wslconfigのmemory)の1/4でギガバイト単位に切り上げた数値を使う。

設定したswap領域のサイズは、前述のfreeコマンドで表示できるほか、swaponコマンドや/proc/meminfoで得ることができる。

スワップファイルの位置は、“swapfile”キーで絶対パスを指定する。デフォルトは、ユーザーフォルダ-の下にあるAppData\local\Tempフォルダー($env:LOCALAPPDATA\Temp\)に置かれるvhdxファイルである。Windows 10と11では、フォルダーは同じだが、vhdxのファイル名が異なる(いまのところ、ここにvhdxファイルを置くのはWSL2ぐらいなので判別は容易)。

swap領域は最大サイズが256ギガバイトに指定された容量可変形式のVHDXファイルである。.wslconfigのswapで指定できる最大サイズは250ギガバイトまでに制限されている(それ以上はエラーで指定不可)。

VHDXの容量可変形式では、未使用セクター部分をファイルとしては確保しないため、初期状態では、さほど大きくない(63メガバイト)。swap領域の利用でファイルサイズは大きくなるものの、WSL2仮想マシンの終了時に消去されるため、大きなファイルが残り続けることはない。しかし.wslconfigのswapキーで指定したサイズ程度の空き容量は必要である。

CPU関連設定

.wslconfigのCPU関連の設定としては、“processors”と“nestedVirtualization”の2つがある。前者は、WSL2仮想マシンに割り当てるCPUのコア数、後者は、WSL2内で仮想マシン支援機能の有無を指定するもの。

“processors”は、値として整数値を指定し、上限は、物理プロセッサのコア数である。特に事情がなければこの項目を指定する必要はない。

“nestedVirtualization”は、ホストCPUが持つ、Nested VM機能を使い、WSL2仮想マシンの中でさらに仮想マシン支援機能を有効にするためのもの。Nested VMは、インテルCPUならば第5世代以降、AMDはZenアーキテクチャ以降が持っている機能だ。

Windows 11上のWSL2で利用できるが、Windows 10では利用できない。設定値としては“true”(有効。デフォルト値)または“false”(無効)を指定する。実際に利用するには、QEMUなどの仮想マシン支援ソフトウェアが必要になる。

CPU関連設定に関しては、lscpuコマンドを使うことで情報を表示できる。lscpuコマンドは、procfsの“/proc/cpuinfo”の情報を要約したものになっている(写真04)。“processors”の指定は、/proc/cpuinfoでは、“processor”の出現回数(0から始まるプロセッサ番号を表示している)、lscpuでは、“CPU(s):”で確認する。Nested VMがWSL2内で有効になっているかどうかは、lscpuの“Virtualization:”、/proc/cpuinfoでは、フラグ情報(flags)に“VMX”(インテル)、“SMX”(AMD)があるかどうかで確認できる。

  • 写真04: lscpuコマンドは、CPUの情報を表示する。これでWSL2に割り当てられたコア数やnestedVirtualizationなどの状態を調べることができる

カーネル関連

.wslconfigのLinuxカーネル関連の設定としては、“kernel”、“kernelCommandLine”がある。WSL2では、ユーザーが構成を変更するなどしてコンパイルしたカーネルを利用することも可能で、その場合、“kernel”キーを使ってカーネルが置かれているフォルダーのパスを指定する。これに対して“kernelCommandLine”は、カーネルに与えるコマンドライン引数を指定するもの。

自分でカーネルをコンパイルした場合には、そのパスを指定し、引数などを指定する必要が出てくるが、Microsoftが提供する標準カーネルを利用している場合には、特に指定する必要はない。

検証方法は特にないが、これらを指定したときWSL2が起動しなければ、少なくともカーネルファイルや引数などに何か間違いがあると考えられる。

なお、起動時のdmesgメッセージに関しては、.wslconfigの“debugConsole”をtrueに指定することで、WSL2の起動時にカーネルが出力するメッセージを表示させることができる(写真05)。

  • 写真05: debugConsoleを有効にすると別ウィンドウにLinuxのカーネルメッセージ(dmsg)を表示できるようになる。これによりkernelCommandLineで指定したコマンドなどを表示させることが可能だ

その他の設定

その他の設定のうち解説が必要なものには“vmIdleTimeout”がある。

“vmIdleTimeout”は、すべてのWSL2ディストリビューションが終了したあと、WSL2仮想マシンを終了させるまでのアイドル時間をミリ秒単位で設定する。この時間が経過すると、WSL2仮想マシンは終了し、メモリなどWSL2仮想マシンが専有していたリソースが開放される。一回開放されるとWSL2を起動するときに環境設定などに時間が必要になる。この時間を長くするとWSL2を終了させても割り当てられたメモリなどのリソースが開放されるまでの時間が長くなる。

.wslconfigファイルは、比較的重要な設定項目ではあるが、大半のものはデフォルト値のままで問題ない。また、設定はすべてのディストリビューションに有効になるため、複数のディストリビューションを利用する場合には慎重に行う必要がある。

>> Windows Subsystem for Linuxガイド 連載バックナンバー
https://news.mynavi.jp/tag/winsubsystem/