这几天思考了一下Windows下个人对于虚拟化的要求,以及虚拟机的实际使用情况,发现Windows下除了Linux开发环境用VM开的非常多,平常很少使用到VM。而且目前已经几乎不会使用VMware Workstation单独开一个带桌面环境的Linux VM。
然后,突然发现目前自己的需求挺适合使用WSL的。所以就花了点时间配置了一下WSL 2,相比之前版本的WSL 2,目前的版本用起来确实不错。
本文发布时,正式版WSL版本为2.0.9。
先简单的介绍一下WSL
WSL,全称为Windows Subsystem for Linux,是一个在Windows环境下执行Linux程序的兼容层。WSL的首个版本最早发布于2016年8月。
早期的WSL1是真正意义上的兼容层。对,就是在Windows内核里实现Linux系统调用。由于种种原因和困难,WSL1最后停止了开发。
2019年5月,WSL2发布。WSL2实际上来说是一个轻量的Hyper-V虚拟机,然后这个虚拟机通过容器技术来运行多种多样的发行版。在虚拟机里直接运行Linux的难度,相比在Windows内核内实现Linux系统调用,要简单的多。
WSL2经过数年的发展,现在可以直接在WSL内运行GUI程序,使用主机的GPU加速。后来WSL2加入了CUDA支持,现在在WSL2内可以直接使用CUDA跑深度学习等需要CUDA的东西,效率比在Windows上跑要快很多(不过达不到直接在Linux上跑的效率,虚拟机肯定会有损耗)。
你是否适合使用WSL2?
如果你是想完整的学习Linux,那我还是建议你使用虚拟机软件装一个比较容易入门的Linux发行版,以避免撞WSL独有的一些坑。WSL2我只推荐已经熟悉Linux,然后需要一个方便的开发环境的读者使用。
因为WSL2使用了Hyper-V技术,因此依赖虚拟机的用户,或对Hyper-V反感的用户,请慎重考虑。
简单来说就是下面四点:
- 如果你能完善的解决Hyper-V的问题,就可以上WSL2。
- 当前VMware Workstation和Oracle VM VirtualBox最新版本可以和Hyper-V共存,但是可能有小问题,得看你能不能接受。
- 手游模拟器用户请确认你目前使用的模拟器是否支持和Hyper-V共存。
- 如果你使用的某些其他软件也需要虚拟化技术,请确认这些软件是否可以和Hyper-V共存。
另外个人觉得WSL2是专门设计给开发者使用的,所以开发环境下用用还是不错的。不是很推荐在生产环境下使用?(哎呀都生产环境了你咋不直接上Linux实体机系统呢)
以下是一些补充说明,可以不看。
目前有Windows Hypervisor Platform(下文简称WHP),情况已经比当年好一些了,但是,也不是所有软件都适配了这玩意。
目前Windows下常用的两个桌面级Type-2 Hypervisor(VMware Workstation和Oracle VM VirtualBox)的最新版已经支持WHP,也就是已经可以和Hyper-V共存,不过可能会产生一些小问题,得看你能不能接受:
- VMware Workstation和VirtualBox与Hyper-V共存时会失去嵌套虚拟化能力,不过正常情况下应该没人玩虚拟机套娃吧。
- VMware Workstation:目前运行绝大多数最新版操作系统应该没有什么太大问题。运行部分早期的操作系统(比如Windows 2000)可能会出现性能下降。另外VMware Workstation 16.2及之后的版本,Linux VM可能出现键盘输入卡顿的情况(目前确定是VMware Workstation的锅,看什么时候修复了)。
- VirtualBox:略微的性能下降,但是用着没有太大问题。
市面上大部分模拟器都基于VirtualBox,不过即便如此,目前很多手游模拟器依然还不支持Hyper-V,建议事先确认你使用的手游模拟器是否支持Hyper-V。
UPDATE on Jan 18, 2024:博主目前试了下Bluestacks 5国际版最新版本,可完美兼容Hyper-V,且性能还不错。
至于我,我直接把用了多年的VMware Workstation扬了,换成Hyper-V,毕竟我感觉我自己跑虚拟机很少用3D加速。
安装WSL2
在“启用或关闭Windows功能(Turn Windows features on or off)”界面,打开“虚拟机平台(Virtual Machine Platform)”和“Windows虚拟机监控程序平台(Windows Hypervisor Platform)”。打开这两个功能应该会提示需要重启一次。
在重启完成后,前往Microsoft Store下载WSL2。下载完成后你就拥有了WSL2本体了,不过,你还得装一个发行版,才能开始使用WSL2。
Microsoft Store里已经有相当多的WSL2发行版了,如果你在这里找到了你想用的发行版,直接在这里安装就可以了。
当然,你也可以自己构建一个发行版的文件系统,并提供给WSL2使用。下面我们即将在WSL2里安装Arch Linux,就需要这么做。
向WSL安装Arch Linux
除了直接安装商店里的WSL发行版之外,你还可以自行制作你想用的Linux发行版的rootfs,打包成tar.gz
格式,然后手动导入WSL。
# 导入发行版
wsl --import <DistroName> <InstallLocation> <InstallTarFile>
# 设置默认启动的发行版
wsl -s <Distro>
现成的rootfs
目前已经有开发者制作了现成的Arch Linux rootfs,如果你不想手动制作rootfs,或者是为了方便,可以直接使用,不过在使用时记得阅读相关的说明。
这里推荐使用yuk7的ArchWSL:GitHub。该rootfs可同时用于WSL1和WSL2。
另外我个人也同时制作了一个专门针对WSL2,定时更新最新版的rootfs,也可以看一下:GitHub。
另外,不管用的是谁的rootfs,在配置完成后记得及时更新系统(pacman -Syu
)。
制作一个rootfs
你首先需要有一个现成的Arch Linux环境。
当然,你可以使用别的发行版,如果你打算如此,请确保你所使用的发行版下,Arch Linux的包管理pacman
可以正常工作。
下面的制作rootfs命令仅供参考。
pacman -S arch-install-scripts
# /tmp/rootfs-skeletion 和 /tmp/rootfs 可以换成你喜欢的路径
sudo mkdir /tmp/rootfs-skeletion
# 这里需要保证/tmp/rootfs是挂载点,防止后面配置出问题
sudo mount --mkdir --bind /tmp/rootfs-skeletion /tmp/rootfs
# 接下来两步你应该比较熟悉
# 请根据你的实际需要更改pacstrap步骤安装的包
pacstrap -K /tmp/rootfs base curl wget vim sudo texinfo man-db man-pages
arch-chroot /tmp/rootfs
# 接下来按照你喜欢的方式配置rootfs
# 清理包换成以缩减rootfs.tar.gz的体积
rm -rf /tmp/rootfs/var/cache/pacman/pkg/*
# 打包rootfs.tar.gz
tar -czf ~/rootfs.tar.gz -C /tmp/rootfs ./
# 清理工作
sudo umount /tmp/rootfs
sudo rmdir /tmp/rootfs
sudo rm -rf /tmp/rootfs-skeletion
将rootfs.tar.gz复制到Windows,然后将其导入WSL即可使用。
若在之前的步骤中没有配置非root账号和sudo,在正式使用前,建议先创建一个非root账号并配置好sudo。
同时在正式使用之前,建议关闭WSL自动追加Windows PATH环境变量的设置。
pacman -S sudo
echo '%wheel ALL=(ALL:ALL) ALL' > /etc/sudoers.d/wheel
useradd -m -G wheel azurezeng
passwd azurezeng
cat << EOF > /etc/wsl.conf
[interop]
appendWindowsPath=false
[user]
default=azurezeng
EOF
这样我们就得到了Arch Linux on WSL。(下图的WSL Linux内核版本由我本人进行编译,因此与WSL自带的Linux内核版本不一致)
使用Docker Desktop
直接去Docker Desktop官网下载,非常简单。
不过这个是大企业需要考虑的事情的,个人使用没啥顾虑。
在安装完成后,除了在Windows上直接调用docker
,Docker Desktop会自动与默认的WSL发行版集成,可以手动设置Docker Desktop和哪些WSL发行版集成。
一些个人遇到的坑
systemd
有的时候可能需要使用到systemd的服务管理功能。在/etc/wsl.conf
中设置相关选项以启用systemd支持。
[boot]
systemd=true
同时建议关闭systemd-journald
的日志持久化功能(就是让journald的日志只保存在内存中),以节约硬盘空间。
# /etc/systemd/journald.conf.d/wsl.conf
[Journal]
Storage=volatile
RuntimeMaxUse=200M
WSLg
首先我遇到的第一个问题是,WSL启动时会调用NVIDIA独立显卡,会导致笔记本发热量上升。之前尝试了各种方法都没有完美的解决这个问题。最近发现在.wslgconfig
里指定环境变量MESA_D3D12_DEFAULT_ADAPTER_NAME=Intel
(我是Intel集成显卡用户)可以让WSLg的相关进程优先调用集成显卡,问题完美解决,不过我的办法在WSLg官方的文档里没有详细说明。
以及我不是很想WSL内的安装的程序在开始菜单中出现,这个官方给了相关设置。
至于分数缩放,只能说无解咯,目前(2023年末左右)原生Linux桌面环境普遍对分数缩放不好。
关于WSLg配置文件~/.wslgconfig
里设置选项,可以参考官方的相关文档。这里也放出自己的.wslgconfig
以供各位参考。
[system-distro-env]
WESTON_RDP_APPLIST=false
; Suppress wakeup of NVIDIA discrete card
;LIBGL_ALWAYS_SOFTWARE=1
; Prefer using Intel integrated graphics card
MESA_D3D12_DEFAULT_ADAPTER_NAME=Intel
WSL 2.0.x下内存回收和硬盘空闲空间回收
先前的WSL有着比较让人不舒适的内存泄露问题,目前在~/.wslconfig
内设置autoMemoryReclaim=dropcache
可以解决问题(此选项在2.1.3版本之后为默认值)。
同时,可以设置sparseVhd=true
,之后新安装的发行版均会自动回收其虚拟硬盘文件的空闲空间。对于已经安装的发行版,可以使用wsl --manage <Distro> --set-sparse <true/false>
为发行版的虚拟硬盘文件启用该功能。
[wsl2]
autoMemoryReclaim=dropcache # dropcache/gradual/disabled,设置成gradual则发行版内不建议打开systemd功能
[experimental]
sparseVhd=true
WSL 2.0.x下的mirrored网络
mirrored
网络可让WSL的网络环境和主机环境一致(主机和WSL内的端口互通),并支持IPv6。此功能对宿主机的要求为Windows 11 22H2 Build 22621.2338+。
目前Docker Desktop已对networkingMode=mirrored
提供较好支持。直接在发行版中运行的Docker CE,需要在/etc/docker/daemon.json
中设置"iptables": false
,虽然个人觉得这么做不是很优雅。
[experimental]
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true
hostAddressLoopback=true
关于WSL的NAT网络下的宿主机IP固定
若因为部分特殊原因,不打算使用mirrored网络,或未对WSL网络相关选项进行配置,则默认使用NAT网络。
Linux下,可以通过ip addr
查看WSL的IP地址。Windows下可以通过ipconfig
查看NAT虚拟网卡的IP地址。
PS E:\Temp> wsl ip -color=auto addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 10.255.255.254/32 brd 10.255.255.254 scope global lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:15:5d:57:3d:49 brd ff:ff:ff:ff:ff:ff
inet 172.17.228.46/20 brd 172.17.239.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::215:5dff:fe57:3d49/64 scope link
valid_lft forever preferred_lft forever
PS E:\Temp> ipconfig | grep -A 7 WSL
Ethernet adapter vEthernet (WSL (Hyper-V firewall)):
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::f1a0:df8c:1ebd:968c%65
IPv4 Address. . . . . . . . . . . : 172.17.224.1
Subnet Mask . . . . . . . . . . . : 255.255.240.0
Default Gateway . . . . . . . . . :
PS E:\Temp>
之前Windows侧用于给WSL进行NAT网络的虚拟网卡,在每次重启后其IP都会变动,导致WSL内程序访问宿主机上的程序会非常的不舒服。虽然之前有相当多的解决方案,但是依然不是很完美的。
这个问题在某次WSL更新后得到了解决。现在宿主机的IP和WSL的IP都在注册表内,可以手动修改。
- WSL的IP地址:
HKCU\Software\Microsoft\Windows\CurrentVersion\Lxss\NatIpAddress
- 宿主机中的NAT设置:
HKLM\Software\Microsoft\Windows\CurrentVersion\Lxss\NatNetwork
- 宿主机中的NAT虚拟网卡IP地址:
HKLM\Software\Microsoft\Windows\CurrentVersion\Lxss\NatGatewayIpAddress
修改完以上注册表之后建议重启Windows以应用更改。
内核更换(仅建议专业用户考虑)
如果WSL自带的Linux内核版本无法满足你的需求,可以在.wslconfig
中编辑使用自定义内核。需要注意的是,如果你使用的内核不带dxgkrnl
驱动,则会导致WSL的GPU加速失效。
如果发现WSL有一些问题,若设置了自定义内核则建议先禁用自定义内核再排错。
[wsl2]
kernel=E:/Virtual Machines/WSL/Kernels/linux-6.6.11-bzImage
这里附上目前我目前正在使用的最新LTS内核的GitHub Repo:Nevuly/WSL2-Linux-Kernel-Rolling。
一些杂项问题
部分情况下WSL发行版内的ping
命令可能会需要root权限才能使用,否则报错。解决办法为修改WSL的内核命令行参数(kernelCommandLine
),向WSL传入net.ipv4.ping_group_range=\"0 2147483647\"
的sysctl选项来解决问题。
另外我偶尔可能也要设置WSL的内存使用上限(WSL 2.0.x之前我一般设置WSL的内存上限为8GB),这个可以透过memory
选项达到。
[wsl2]
#memory=8GB
kernelCommandLine=sysctl.vm.overcommit_memory=1 sysctl.net.ipv4.ping_group_range=\"0 2147483647\"
现在在Arch能调用vulkan程序吗,我尝试安装arch仓库里面的mesa,是不行的只能调用opengl。如果我手动编译安装mesa然后指定vulkan-drivers=microsoft-experimental后就可以运行vulkan程序,但是opengl的运行不了了。
找到问题了arch官方包里面vulkan-drivers没有包含microsoft-experimental,而且microsoft-clc也是disable的,我在aur里面找到了mesa-enable-h264这个包,他pkgbuild把所有的特性都选成All,换成这个了之后就可以用了。
毕竟arch in wsl不受arch官方支持
还是没法回收磁盘, 我编一下sdk少2g, 编着编着磁盘就没了=-=, 以前可以
mount /dev/sda -o remount,ro
zerofree /dev/sda
但是更新之后没法mount根目录了=-=
有办法手动回收磁盘嘛, 研究了很久没找见方法.
我这边sparseVhd是有效的,不是很清楚你那边什么情况,因为WSL的sparse VHD,内部用的技术目前是不清楚的