WSL2开发使用小贴士

WSL 1 和 WSL 2 有哪些关键不同?以及使用 Linux 工具链时,如何获取最大的文件性能?


WSL概述

适用于 Linux 的 Windows 子系统(Windows Subsystem for Linux,WSL)是 Windows 的一项功能,用于在 Windows 计算机上运行 Linux 环境,而无需完整的虚拟机。

目前 WSL 有 WSL 1 和 WSL 2 两个版本,虽然都是为了在 Windows 上运行 Linux 环境,但它们的实现方式完全不同。

功能 / 特点 WSL 1 WSL 2
架构 系统调用的翻译层 Hyper-V 轻量级虚拟机
文件系统 Windows NT 层模拟 Linux 文件系统 ext4 格式的 VHDX 文件系统
完整 Linux 内核
完整的系统调用兼容性
systemd 支持
读写 Linux 上文件的性能 🚲 🚀
读写 Windows 上文件的性能 🚀 🐌

比较实现方式

WSL 1 是一个翻译层,在 Windows NT 内核上模拟 Linux 系统调用层,不是虚拟机也没有 Linux 内核

WSL1 的机制是:

  1. Windows 截获 Linux 程序发出的系统调用;
  2. 转换成 Windows 的系统调用;
  3. 在 Windows 内核中执行。

比较文件系统

WSL 1 的文件操作本质上都是 Windows 的 NTFS 文件系统在操作:

  • 访问 Windows 文件:Windows 磁盘看似“挂载”在 /mnt 下,实际上翻译层会直接将文件路径 /mnt/c/xxx 转换为 Windows 路径 C:\xxx,相当于 NTFS 直接访问原始文件,速度快
  • Linux 根文件系统:在 NTFS 上仿真实现 Linux 文件系统的行为,增加额外的仿真开销,速度稍慢

对文件读写性能进行排序:WSL 2 读写 Linux 文件 > WSL 1 读写 Windows 文件 > WSL 1 读写 Linux 文件 > WSL 2 读写 Windows 文件。

WSL2读写性能测试

若想获得最快的性能速度,请将文件存储在 WSL 文件系统中,使用 Linux 工具在 Linux 命令行中处理这些文件。跨操作系统访问文件可能会显著降低性能。

WSL 文档 - 最佳设置实践

WSL 2 操作 Linux 文件和 Windows 文件的性能差距有多大呢?让 AI 生成个脚本简单测试下:

>folded wsl_fs_benchmark.sh
#!/bin/bash

echo "=== WSL2 Disk I/O Benchmark ==="
echo

TEST_SIZE_MB=512
SMALL_FILES=2000

# Locations
EXT4_DIR="$HOME/wsl_test_ext4"
WIN_DIR="/mnt/d/wsl_test_win"

mkdir -p "$EXT4_DIR" "$WIN_DIR"

benchmark_seq_write() {
DIR=$1
echo "[SEQ WRITE] Testing $DIR ..."
dd if=/dev/zero of=$DIR/testfile bs=1M count=$TEST_SIZE_MB conv=fdatasync 2>&1 | grep -E --color=never 'copied'
}

benchmark_seq_read() {
DIR=$1
echo "[SEQ READ] Testing $DIR ..."
dd if=$DIR/testfile of=/dev/null bs=1M 2>&1 | grep -E --color=never 'copied'
}

benchmark_small_files() {
DIR=$1
echo "[SMALL FILES] Creating $SMALL_FILES files in $DIR ..."
START=$(date +%s.%N)
for i in $(seq 1 $SMALL_FILES); do
echo "hello" > "$DIR/small_$i.txt"
done
END=$(date +%s.%N)
TIME=$(echo "$END - $START" | bc)
echo "Time: $TIME seconds"
}

echo "------------------------------------------"
echo "Testing ext4 (/home)"
echo "------------------------------------------"
benchmark_seq_write "$EXT4_DIR"
benchmark_seq_read "$EXT4_DIR"
benchmark_small_files "$EXT4_DIR"

echo
echo "------------------------------------------"
echo "Testing Windows (/mnt/d)"
echo "------------------------------------------"
benchmark_seq_write "$WIN_DIR"
benchmark_seq_read "$WIN_DIR"
benchmark_small_files "$WIN_DIR"

echo
echo "Benchmark complete!"

在 i5-12500H(4E8P)和 NVMe SSD 的环境下,测试结果如下:

>folded 原始测试结果
$ ./wsl_fs_benchmark.sh
=== WSL2 Disk I/O Benchmark ===

------------------------------------------
Testing ext4 (/home)
------------------------------------------
[SEQ WRITE] Testing /home/thinklong/wsl_test_ext4 ...
536870912 bytes (537 MB, 512 MiB) copied, 0.592031 s, 907 MB/s
[SEQ READ] Testing /home/thinklong/wsl_test_ext4 ...
536870912 bytes (537 MB, 512 MiB) copied, 0.102132 s, 5.3 GB/s
[SMALL FILES] Creating 2000 files in /home/thinklong/wsl_test_ext4 ...
Time: .079443942 seconds

------------------------------------------
Testing Windows (/mnt/d)
------------------------------------------
[SEQ WRITE] Testing /mnt/d/wsl_test_win ...
536870912 bytes (537 MB, 512 MiB) copied, 4.79956 s, 112 MB/s
[SEQ READ] Testing /mnt/d/wsl_test_win ...
536870912 bytes (537 MB, 512 MiB) copied, 3.87322 s, 139 MB/s
[SMALL FILES] Creating 2000 files in /mnt/d/wsl_test_win ...
Time: 10.715896161 seconds

Benchmark complete!
---
config:
  theme: 'base'
  xyChart:
    width: 600
    height: 150
    plotReservedSpacePercent: 50
    showDataLabel: false
  themeVariables:
    xyChart:
      darkMode: true
      fontSize: 16px
      backgroundColor: '#000'
      titleColor: '#fcee09'
      labelFontSize: 16
      xAxisLabelColor: '#fff'
      xAxisTitleColor: '#fff'
      xAxisTickColor: '#fff'
      xAxisLineColor: '#fff'
      yAxisLabelColor: '#fff'
      yAxisTitleColor: '#fff'
      yAxisTickColor: '#fff'
      yAxisLineColor: '#fff'
      plotColorPalette: '#fcee09, #02d7f2'
---
xychart horizontal
  title "WSL2操作不同文件系统的性能"
  x-axis ["顺序读", "顺序写", "创建小文件"]
  y-axis "速度(GB/s)" 0 --> 5.5
  bar [5.3,0.89,5.36]
  bar [0.14,0.11,0.04]
测试项目 Windows Linux
顺序读(GB/s) 0.14 5.3
顺序写(GB/s) 0.11 0.89
创建大量小文件用时(秒) 10.72 0.08

可以看到在 WSL 2 中,Linux 工具处理 Linux 文件的性能远远大于挂载的 Windows 文件。因此,官方文档强烈建议将文件存储在 Linux 文件系统中。

使用代理

想要在 WSL 2 内使用 Windows 宿主机上的代理,首先要知道 Widnows 在 WSL2 中的 IP 地址,可以通过下面两种方式来获取:

# 方式一(推荐): 查询路由表, 获取 Windows 主机在 WSL2 网络中的 IP
# WSL2 的默认路由指向一个 NAT 网关,网关地址就是 Windows 主机在 WSL2 网络中的 IP
HOST_IP=$(ip route | awk '/default/ {print $3}')

# 方式二: 调用 powershell.exe, 获取 Windows 主机在物理网络中的真实 IP
# 这里获取的是无线网卡(WLAN)的 IPv4 地址
HOST_IP=$(powershell.exe -Command "Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias 'WLAN' | Select-Object -ExpandProperty IPAddress" | tr -d '\r')

两种方式获得的 IP 地址不同,但都可以访问并使用到代理,只是访问路径会有略微差别:

  • 方式一:WSL 2 直接通过 Hyper-V 虚拟交换机访问到 Windows 主机。
  • 方式二:WSL 2 经过 NAT 网关通过 Windows 主机在物理网络中的真实 IP 访问。

脚本:

set_proxy.sh
#!/bin/bash

# 获取 Windows 主机 IP
HOST_IP=$(ip route | awk '/default/ {print $3}')

# 设置全局 http(s) 代理
export http_proxy="http://$HOST_IP:7890"
export https_proxy="$http_proxy"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$http_proxy"

# 设置全局 git 代理地址
git config --global http.proxy "$http_proxy"
git config --global https.proxy "$http_proxy"

管理维护

迁移wsl实例

wsl 实例默认位于 C 盘,如果需要迁移已有实例到其他磁盘,可以走先备份再导入的流程实现迁移。

# 关闭wsl
PS > wsl --shutdown

# 查看wsl实例名称
PS > wsl -l -v
NAME STATE VERSION
* Ubuntu-24.04 Stopped 2

# 导出当前的Ubuntu-24.04实例
PS > wsl --export Ubuntu-24.04 D:\wsl\Ubuntu-24.04_20260127.tar
正在导出,这可能需要几分钟时间。 (40229 MB)
操作成功完成。

# 注销原来的实例,会删除原来的ext4.vhdx文件
# 注销操作可以放在验证完导入结果之后进行,但新的实例就需要更换名称避免冲突
PS > wsl --unregister Ubuntu-24.04
正在注销。
操作成功完成。

# 导入Ubuntu系统
# 依次传入实例名称,ext4.vhdx文件保存的位置,使用的备份文件
PS > wsl --import Ubuntu-24.04 D:\wsl\Ubuntu-24.04\ D:\wsl\Ubuntu-24.04_20260127.tar --version 2
操作成功完成。

# 进入wsl
PS > wsl

# 迁移后发现默认登录用户变为了root,修改Ubuntu默认登录用户为thinklong
PS > ubuntu2404.exe config --default-user thinklong

给磁盘瘦身

使用 diskpart 工具回收 VHDX 内已经释放但尚未回收的空间,适合在,可以减小 ext4.vhdx 文件体积:

# 关闭wsl
PS > wsl --shutdown

# 查看wsl实例名称
PS > wsl -l -v
NAME STATE VERSION
* Ubuntu-24.04 Stopped 2

# 查看wsl使用的ext4.vhdx文件位置,注意替换'Ubuntu-24.04'为你的版本
PS > (Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq 'Ubuntu-24.04' }).GetValue("BasePath") + "\ext4.vhdx"
C:\Users\chikai\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx

# 使用diskpart压缩vhdx文件
# diskpart的操作是立即生效的,且不可撤回,注意避免误操作
PS > diskpart
Copyright (C) Microsoft Corporation.
在计算机上: THINKBOOK14PLUS
DISKPART> select vdisk file="C:\Users\thinklong\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx"
DiskPart 已成功选择虚拟磁盘文件。
DISKPART> attach vdisk readonly
100 百分比已完成
DiskPart 已成功连接虚拟磁盘文件。
DISKPART> compact vdisk
100 百分比已完成
DiskPart 已成功压缩虚拟磁盘文件。
DISKPART> detach vdisk
DiskPart 已成功分离虚拟磁盘文件。
DISKPART> exit
退出 DiskPart...

参考资料

WSL 文档 - 比较 WSL 版本
WSL 文档 - 跨文件系统的文件存储和性能

WSL2开发使用小贴士

https://thinklong.me/develop-on-wsl2/

作者

ThinkLong

发布于

2025-09-10

更新于

2026-01-30

许可协议

评论

+