-
Notifications
You must be signed in to change notification settings - Fork 4
在 WSL 中通过 Unix Domain Socket 启动图形应用
-
在 Windows 上安装打过 AF_UNIX 补丁的 VcXsrv (X-Org 服务器的 windows 移植). 添加以下启动参数以使用 AF_UNIX:
-listen unix
. -
在 WSL 上安装打过 AF_UNIX 补丁的 libxcb.
-
创建符号链接:
/tmp/.X11-unix
->/mnt/c/tmp/.X11-unix
. -
在 WSL 中测试环境是否可用:
DISPLAY=unix:0 gnome-terminal
.
-
在 Windows 上安装打过 AF_UNIX 补丁的 PulseAudio. 添加以下模块以使用 AF_UNIX:
module-native-protocol-unix socket=C:\\tmp\\pulse\\pulse.sock auth-anonymous=1
. -
在 WSL 上安装打过 AF_UNIX 补丁的 libpulse.
-
在 WSL 中测试环境是否可用:
PULSE_SERVER=/mnt/c/tmp/pulse/pulse.sock paplay -p /mnt/c/Windows/media/ding.wav
在 Windows Subsystem of Linux 中使用图形应用已经不是什么新鲜事了。简单来说,Linux 上的图形应用会通过 X11
协议使用 X-Org
服务器来显示画面,并且通过使用 PulseAudio
服务器来播放声音。以为这套设计具有网络透明性,在 Windows 上也可以通过同样的架构运行。
一般来说 Linux 图形应用会使用 Unix Domain Socket (AF_UNIX) 与视频、音频服务器沟通。但是目前为止所有在 WSL 中使用图形应用的方案都使用了 TCP loopback(连接到 127.0.0.1
的 TCP 连接)通信。
Windows 10 自 1803 开始支持了 Unix Domain Socket,而更妙的是它还支持 Windows 与 WSL 之间的互访。因此,在 Windows 下通过 Unix Domain Socket 来与 X-Org
服务器和 PulseAudio
服务器通信是完全可行的。所以我自己做了一点移植来实现这个功能。
我使用了 VcXsrv
作为给 X-Org
打补丁的实现(要我说它和其他实现一样都是 XWin
的 fork)。以下是编译好的安装包:
完妆完成后通过以下命令启动 X-Org
服务器:
.\vcxsrv.exe -nolisten tcp -listen unix -multiwindow
这条命令会在 0
号显示端口启动服务器。启动完毕后可以通过以下方法验证是否可用:右键任务栏中的 X
图标,选择 Applications
然后启动 xcalc
。如果运作正常的话你会看到一个计算器窗口。
一个坏消息是 socket path 是无法人为指定的,因为在 Linux 中就不行。Socket path 在代码中是写死的,具体的值是 /tmp/.X11-unix/X#
,其中 #
是显示端口。在 Windows 中这个地址会被转换成 C:\tmp\X11-unix\X#
。
以下是编译好的二进制:
这个没有安装包所以解压就可以用。然后你需要修改启动脚本才能使用 Unix Domain Socket。启动脚本默认的位置是 .\etc\default.pa
。或者你可以把启动脚本复制到 ~\.config\pulse\default.pa
然后修改这个。在 network access 那里添加这一行(socket path 的位置可以任意修改,但必须在 NTFS 上且不能是 WSL 的路径):
load-module module-native-protocol-unix socket=C:\\tmp\\pulse\\pulse.sock auth-anonymous=1
然后你可以通过以下命令启动 PulseAudio
:
.\pulseaudio.exe
运行 paplay
来检验服务器是否正常运作:
.\paplay -s unix:C:\tmp\pulse\pulse.sock -p C:\Windows\media\ding.wav
如果运作正常,你会听到「叮」的一声。
理论上说 WSL 上的软件不应该需要移植或修改。然而目前 Windows 上的 Unix Domain Socket 在 Windows 与 WSL 之间互操作的时候有一定限制:socket()
之后必须马上是 bind()
或者 connect()
。其间不能有其它的 syscall。不然这个 socket 就会只能在 WSL 内部使用。所以我对 libxcb 和 libpulse 进行了一些修改,删除了几行代码.
按照说明安装:
然后你需要把 /tmp/.X11-unix
软连接到 C 盘实际上的 socket path:
sudo ln -s /mnt/c/tmp/.X11-unix /tmp/
检验一下是否正确:
ls -l /tmp/.X11-unix
检验一下是否可用(先启动 VcXsrv
):
DISPLAY=unix:0 gnome-terminal
按照说明安装:
检验一下是否可用(先启动 PulseAudio
):
PULSE_SERVER=unix:/mnt/c/tmp/pulse/pulse.sock paplay -p /mnt/c/Windows/media/ding.wav
Unix Domain Socket 比 TCP loopback 性能更好吗?
- 很有可能。我用 MacBook Air 做了一个测试,用它在 2K 分辨率下全屏播放一个 YouTube 上的过山车视频,过山车画面变化很快所以 X11 很容易满载,此外也比较方便观察画面撕裂。然后我发现切换到 AF_UNIX 后 CPU 使用率下降了大约 20%。但是这个实验不够严谨,还需要更多的证据证明性能优势。
我可以在 WSL2 里用吗?
- 目前不行。据我所知最初版本的 WSL2 不支持 AF_UNIX 互操作。当然他们也可能在正式发布之前变卦。
我不信任二进制分发
- Cherry-pick 补丁的分支然后自己编译嘛。