はじめに
手元のPCがWindows機ということもあって、ちょこっとubuntuとか、Windowsと連携させたいときは、WSL2を使っていたりです。素のubuntu機とWSL2の違いが気になったので、掘ってみた、の備忘録です。
NW周り
デフォの状態のWSL2は、NAT経由で、WindowsのNWカード(NIC)を使って通信。NAT経由の場合、IPv4のみでIPv6は疎通できない。
mirroredが推奨されているようだが、自分の環境ではエラーを吐かれてしまったので、非推奨となってしまったbridged(on wiredなNIC、Hyper-Vで設定)で、WSL2上でIPv6も疎通。
netshなportproxyのお世話にならずとも、WSL2上で動いているtcp/udp daemonへの外部PCからのアクセスも無問題。
余談(2025/12/30追記)
自分はWSL2でudp daemonを動かして外部から使う使い方をしていなかったため、気が付かなかったが、WSL2(nat)の場合、Microsoft推奨のnetshでportproxyの方法だと、tcp daemonのtcp portしかproxyできないみたい。
WSL2(nat)でudp daemonのudp portをproxyするには、hyper-Vの助けが必要[udp-proxy-WSL2-nat]な見たい。
[udp-proxy-WSL2-nat] https://x.com/wildlarva/status/1690226619305381888
→ https://gist.github.com/wildlarva/0539212ad6bf0bf1450b38726e1a42de
グラフィックディスプレイ周り
Waylandベース [WSLg] だが、Xのプログラム(xeyes等)も動く。
[WSLg] https://devblogs.microsoft.com/commandline/wslg-architecture/#wslg-architecture
手元のubuntu機は、xrdp経由で使っているため、Waylandのみで動くアプリを試すときにWSL2は便利。
waypipe [waypipe] なるものを使うとssh上に転送できるので、WSL2からwaypipe+sshでubuntu機にログインしてその上でアプリを動かし、WSL2のWSLg(Wayland)で表示なんてこともできる。
[waypipe] https://gihyo.jp/admin/serial/01/ubuntu-recipe/0666
オーディオ周り
デフォのオーディオの経路は、WSL2では、pulseaudioなプラグイン(RDPSink/RDPSource)で受けてRDP経由でwindowsのRemoteAppに渡り[WSLg]、windowsの音量ミキサーに。
WSL2$ pactl info
サーバー文字列: unix:/mnt/wslg/PulseServer
ライブラリプロトコルバージョン: 35
・・・
サーバー名: pulseaudio
サーバーバージョン: 16.1-8-g6f04
デフォルトサンプル仕様: s16le 2ch 44100Hz
デフォルトチャンネルマップ: front-left,front-right
デフォルトシンク: RDPSink
デフォルトソース: RDPSource

上は、WSL2内で、「pactl info」してみた結果、下はWindowsの音量ミキサー。
windowsではRemoteAppオーディオとして見える
windows側のRemoteAppオーディオのボリュームを上げ下げすると、WSL2内で再生している音量が上下する。
ビルトインオーディオはこれを書いている時点ではこの経路だけなので、なんとかしたい(16bit/44.1kHzを変更したいとか)ときはWSL2~Windows間で、NW経由で中継するとかの手段が必要な様子。
昔はビルトインオーディオすら無くて、NW経由で中継していた様子です。
昨今の潮流(?)の、「pipewire化してほしい」[PW化]という要望も出ているようだが、現時点では未対応。
[PW化] https://github.com/microsoft/wslg/issues/290#issuecomment-861784843
alsaについては、「~/.asoundrc」を下記のように設定する[ALSA+PA]と、PA経由で良しなにしてくれる。
[ALSA+PA] https://www.reddit.com/r/bashonubuntuonwindows/comments/17jpeu4/comment/kondz4t/?tl=ja
$ cat ~/.asoundrc
pcm.!default { type pulse fallback "sysdefault" hint.description "Default Audio Device (via PulseAudio)" }
ctl.!default { type pulse fallback "sysdefault" }
ちなみに、USBなaudioは、usbipd-winを使っても、貫通できない様子[USB-audio]。
[USB-audio] https://www.sato-susumu.com/entry/2023/01/21/103202
あと、mplayerはデフォでpulseを掴んでくれるが、mpvやcelluloidはデフォでpipewireを掴んでしまうため、--ao=pulseや--mpv-ao=pulseを設定して、pulseaudioに導いて上げないと音が出なかった。
GPU支援
デフォでは、「/dev/dri」が無く、VA-APIとかのGPU支援が使えない。
以前の版では、使えたようだが、今の版では、「modprobe vgem」でモジュールを入れてやると、「/dev/dri」以下が生成されて、「GALLIUM_DRIVER=d3d12」とかいう呪文付きではあるが、「vainfo --display drm」とかでは叩ける[WSL2でvainfo]ようになる。
[WSL2でvainfo] https://github.com/microsoft/WSL/issues/11838
$ ls -l /dev/dri/
合計 0
drwxr-xr-x 2 root root 80 11月 25 14:06 by-path/
crw-rw----+ 1 root video 226, 0 11月 25 14:06 card0
crw-rw----+ 1 root render 226, 128 11月 25 14:06 renderD128
$ GALLIUM_DRIVER=d3d12 vainfo --display drm
libva info: VA-API version 1.20.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/d3d12_drv_video.so
libva info: Found init function __vaDriverInit_1_20
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.20 (libva 2.12.0)
vainfo: Driver version: Mesa Gallium driver 25.2.7 - kisak-mesa PPA for D3D12 (Intel(R) Iris(R) Xe Graphics)
vainfo: Supported profile and entrypoints
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointVLD
VAProfileH264High : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileHEVCMain10 : VAEntrypointVLD
VAProfileHEVCMain10 : VAEntrypointEncSlice
VAProfileVP9Profile0 : VAEntrypointVLD
VAProfileVP9Profile2 : VAEntrypointVLD
VAProfileAV1Profile0 : VAEntrypointVLD
VAProfileNone : VAEntrypointVideoProc
intelなGPUの乗っているwin機のWSL2内で、この状態で、「mpv --vo=gpu --hwdec=vaapi」と引数を付けて動画再生してみたところ、windows上の「LibreHWmonitor」で確認すると、GPUの消費電力が上がり(0.4W→1.1W)、「D3D 3D」のバーも長くなるので、一応、intelなGPUの乗っているwin機の場合は、GPU支援できてるっぽい。
「modprobe -r vgem」しても、「GALLIUM_DRIVER=d3d12」の呪文があれば、mplayerとかmpvとかcelluloidではGPUを使ってくれる様子。
NVIDIAなGPUの乗っているwin機の場合は、「LibreHWmonitor」ではその効能が判別できなかった。
nvtop
nvtopはintelとかAMDとかNVIDIAなGPUの状態が見れるプログラムである。
ubuntu22/24に入っているのはちょっと旧いようなので、githubにある最新版のソース[nvtop公式]から野良ビルドしてみた。
[nvtop公式] https://github.com/Syllo/nvtop
WSL2内となると、NVIDIAなGPUのwin機の場合はちゃんと見れた。(但し、「modprobe vgem」を実行すると「No GPU to monitor」)
intelなGPUのwin機の場合は、WSL2ではあんまりちゃんと対応されていないようで、「GPU支援」の項で記載したvainfoが見える状態にしても、「No GPU to monitor」となってしまう。
$ nvtop-3.2.0-x64-ubuntu24
gpuinfo_metax_init
No GPU to monitor.
ちなみに、同じバイナリでintelなGPUのubuntu機で動かすとちゃんとGPUの状況が表示される。
windowsのコマンドの実行、ディスクの実体
WSL2のディスクの実体の位置は、どうも、vhdxらしく、レジストリに書かれているらしい。[WSL2のディスクの位置]
[WSL2のディスクの位置] https://office365room.com/non-microsoft365/wsl2-virtual-disk-where/
下記のコマンドをPowerShellで実行するとその位置が判明。
PS C:\Users> (Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq '<distribution-name>' }).GetValue("BasePath") + "\ext4.vhdx"
上記は、「 https://office365room.com/non-microsoft365/wsl2-virtual-disk-where/ 」より引用。
これをコアに、sshした先のWSL2内のディスクの位置を知るshell scriptをでっち上げた。
cygwin同様、WSL2内からwindowsのプログラムが叩けることを有効活用。
ちなみに、まともに動かすために、「エスケープシーケンス」に腐心(?)した。(笑)
$ cat ~/scripts/getWSL2diskPath.sh
#!/bin/sh
# show usage
if [ "$1" = "" ];
then
echo "$0 xxx xxx ;; (xxx=IPaddr)"
exit 1
fi
# parse OPTs.
while getopts :s: OPT
do
case $OPT in
*) echo "${OPTARG} is not given (OPT=${OPT}) "
exit 1
;;
esac
done
for i in $*;
do
ping -c ${i} && \
(
ssh xxx@${i} \
'/mnt/c/Program\ Files/PowerShell/7/pwsh.exe \
-Command \(Get-ChildItem -Path HKCU:\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Lxss \| \
Where-Object \{ \$_.GetValue\(\"DistributionName\"\) -eq \"Ubuntu\" \}\).GetValue\(\"BasePath\"\) + \"\\ext4.vhdx\"'
)
done
余談
windowsから実行するwsl.exe、「--system」[wsl-system] なる面白いコマンドオプションがあって、こいつをwindows側から実行すると、WSL2内から見ることができない、WSLgアーキテクチャーのコアの「WSLg System Distro」を垣間見ることができた。(westonとかXwaylandとかのプロセスが見える)
[wsl-system] https://www.reddit.com/r/bashonubuntuonwindows/comments/10ujocg/wsl_system_commandline_option/?tl=ja
PC C:\Users\aaa> wsl.exe --system bash -c '(cat /etc/issue && /bin/ps -ef | grep -i wayland)'
Welcome to CBL-Mariner 2.0.20240829 (x86_64) - Kernel \r (\l)
wslg 12 9 0 Nov24 ? 00:00:02 /usr/bin/weston --backend=rdp-backend.so --modules=wslgd-notify.so --xwayland --socket=wayland-0 --shell=rdprail-shell.so --log=/mnt/wslg/weston.log --logger-scopes=log,rdp-backend,rdprail-shell
wslg 346 12 0 Nov24 ? 00:05:45 /usr/bin/Xwayland :0 -rootless -core -listen 38 -wm 39 -terminate -nolisten local -ac
・・・
何気に、pulseaudioなdaemonとか、pipewireなやつとかも動いている。
$ wsl.exe --system bash -c '(cat /etc/issue && /bin/ps -ef | grep -i -e pulse -e pipew -e wirep )'
Welcome to CBL-Mariner 2.0.20240829 (x86_64) - Kernel \r (\l)
wslg 738 9 0 Nov24 ? 00:00:00 /usr/bin/pulseaudio --log-time=true --disallow-exit=true --exit-idle-time=-1 --load=module-rdp-sink sink_name=RDPSink --load=module-rdp-source source_name=RDPSource --load=module-native-protocol-unix socket=/mnt/wslg/PulseServer auth-anonymous=true --log-target=newfile:/mnt/wslg/pulseaudio.log
wslg 974 954 0 Nov24 ? 00:00:00 /usr/bin/pipewire
wslg 977 954 0 Nov24 ? 00:00:00 /usr/bin/pipewire -c filter-chain.conf
wslg 980 954 0 Nov24 ? 00:00:00 /usr/bin/wireplumber
wslg 981 954 0 Nov24 ? 00:00:00 /usr/bin/pipewire-pulse
・・・
pipewireなRDPプラグインをWSL公式が書いてくれると、WSL2からイマドキなpipewireが使えるようになるかもしれない、と淡い期待。
「wsl --system」とwindowsから叩いてログイン(?)すると、もちろん、「/etc/passwd」には、rootとかもあった。
wslg [ /mnt/c/Users/aaa ]$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/bin/false
daemon:x:6:6:Daemon User:/dev/null:/bin/false
・・・
「su」はあった(パスワードは不明)が、「sudo」は見つからず。
おわりに
素のubuntu機とWSL2の違いが気になったので、掘ってみました。
「WSL2って、素のubuntu機でできる○○ってできるの?」とかお悩みのご同輩の一助になれば幸いです。
履歴
20251230、1.2版 NIC関係のところにWSL2(nat)のudp/tcp proxyの情報を追記。
20251220、1.1版 editorialな修正
20251219、1.0版 (note(2025年11月25日初版)より引っ越し、)

