最近清理WSL2发行版的磁盘,发现大部分空间都被/home占用,所以决定用独立的vhdx磁盘作为/home挂载到发行版里
关于 WSL 2 架构
WSL 2 架构可以参考wsl.dev ,微软于25年5月19开源 了 WSL 2 大部分组件。
WSL 2 内核运行在一个使用[HCS API](Host Compute System Overview | Microsoft Learn )创建的隐藏虚拟机里,各发行版实际上是通过namespace隔离的容器。在内核启动后,WSL 进入其预制的WSLg System Distro 中,加载各已安装发行版的磁盘,并将其挂载到各发行版的mount namespace中(这里写死了是ext4,所以应该是没法去改根目录文件系统的)。
PS:所有发行版共用同一个network namespace
可以通过下面的命令进入system distro:
还可以以root权限进入:
关于 VHD/VHDX
还得是 VHDX
VHD/VHDX有三个很有用的特性:
动态VHD: 支持空间调整
稀疏VHD: 支持自动回收空间
父子VHD: 类似overlayfs
常用的管理命令:
1 2 3 4 5 Resize-VHD Optimize-VHD
关于挂载
WSL2 所有发行版共享同一个内核,通过wsl --mount --vhd --bare <vhd path>挂载的磁盘同时对所有发行版可见
Linux 从 2.4 开始 就支持把一个文件系统挂在多个挂载点上,或者在一个挂载点上挂多个文件系统
mount --bind可以挂载一个目录到另一个目录(与挂载点不同,可以是非空目录,且同样可以被挂载多次)
关于稀疏 VHD (SparseVHD) 稀疏VHD实际上是NTFS的稀疏文件 ,它需要通过特殊的ioctl 设置,通过特殊API写入全0数据时可以回收磁盘空间。但是被WSL加了警告
操作过程 分离/home到 VHDX 这里笔者选择了 btrfs,创建了一个空白vhdx,作为/dev/sdxx临时挂载在/mnt/home:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 sudo mount /dev/sdxx /mnt/homesudo btrfs subvolume create /mnt/home/@homesudo btrfs subvolume create /mnt/home/@.snapshotssudo umount /mnt/homesudo mount -t btrfs -o subvol=/@home /dev/sdxx /mnt/homesudo rsync -aXS /home/ /mnt/homesudo umount /mnt/homesudo mv /home /home_oldsudo mount --mkdir -t btrfs -o subvol=/@home /dev/sdxx /home
自动挂载配置 在上面配置完后其实就已经可用了,但是WSL再次冷启动时之前挂载的VHDX并不会自动挂载,挂载上了磁盘也需要手动挂载/home,所以还需要进行自动挂载的配置。这里利用了WSL 2内置的systemd进行自动挂载:
在发行版/etc/wsl.conf中进行以下配置:
1 2 [automount] mountFsTab =false
创建/usr/lib/systemd/system/wsl-automount.service:
其中VHDX路径为"C:\\Users\\UserName\\AppData\\Local\\wsl-home\\home.vhdx"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [Unit] Description =WSL2 Auto MountAfter =systemd-binfmt.service systemd-udevd.serviceRequires =systemd-binfmt.serviceBefore =home.mountDefaultDependencies =no [Service] Type =on eshotExecStart =/bin/sh -c '/mnt/c/Windows/System32/wsl.exe --mount --vhd --bare "C:\\Users\\UserName\\AppData\\Local\\wsl-home\\home.vhdx" || true' StandardOutput =nullStandardError =nullRemainAfterExit =yes TimeoutStopSec =5 [Install] WantedBy =basic.target
创建/usr/lib/systemd/system/home.mount
使用lsblk -f查看磁盘UUID
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [Unit] Description =Mount VHD FilesystemAfter =wsl-automount.serviceRequires =wsl-automount.serviceBefore =shutdown.targetConflicts =shutdown.targetDefaultDependencies =no [Mount] What =UUID=a936001a-3044 -4285 -8 a4a-8 be821931f08Where =/homeType =btrfsOptions =compress=zstd,noatime,subvol=/@home[Install] WantedBy =basic.target
创建'/usr/lib/systemd/system/\x2esnapshots.mount':
快照目录,记得创建/.snapshots
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [Unit] Description =Mount VHD Filesystem @.snapshotsAfter =wsl-automount.serviceRequires =wsl-automount.serviceBefore =shutdown.targetConflicts =shutdown.targetDefaultDependencies =no [Mount] What =UUID=a936001a-3044 -4285 -8 a4a-8 be821931f08Where =/.snapshotsType =btrfsOptions =compress=zstd,noatime,subvol=/@.snapshots[Install] WantedBy =basic.target
可以wsl --shutdown后等待8s,重启wsl检查效果