Skip to content

第 1 章 WSL2:Windows 里秒开 Linux

Part 1 · 环境搭建


引子

你坐在 Windows 电脑前,刚听说学嵌入式开发必须用 Linux。 重装系统?太折腾。装双系统?怕把电脑搞崩。买台新机器? 不太现实。

但如果我告诉你,你的 Windows 里其实已经藏着一台 Linux, 只需要一条命令就能唤醒它呢?

这条路看起来很美好——但 WSL2 和「真正的 Linux」之间有一道看不见的缝隙, 踩对了省你三天,踩错了卡你一周。 这一章我们来做第一次踩点。


背景与动机

先说一个事实:嵌入式 Linux 开发的工具链,99% 跑在 Linux 上。交叉编译器、构建系统(Buildroot、Yocto)、U-Boot 编译、内核配置——这些事情不是在 Windows 上"不能做",而是整个生态就是围绕 Linux 构建的,在 Windows 上硬做只会事倍功半。

所以我们需要一台 Linux 机器。问题是——怎么弄到手?

最硬核的方案是装双系统。优势是性能无损,劣势是你每切换一次系统就要重启一次。想象一下这个场景:你在 Windows 下查了一份芯片数据手册,发现一个寄存器配置可能有问题,需要切到 Linux 改代码重新编译。保存、重启、选启动项、等登录、找到文件、改代码、编译。发现还有问题——再来一遍。一天来回十次,你的耐心和灵感都会被消磨干净。

虚拟机是更常见的方案。VMware 或 VirtualBox 跑一个完整的 Ubuntu 桌面,性能有损耗但可以接受。不过虚拟机有一个不太被人提起的隐性成本:它太"重"了。动辄几十 GB 的虚拟磁盘文件,启动要等几十秒,还得分配固定的内存和 CPU 核心——这些资源哪怕你不用,也被占着。

然后是第三个选项。

如果你的系统是 Windows 10(1903 以上)或者 Windows 11,你的系统里其实已经内置了一种运行 Linux 的能力——WSL2(Windows Subsystem for Linux 2)。它不需要你划分磁盘分区,不需要重启切换,不需要分配固定的内存上限。打开终端,一秒进入 Linux。关掉终端,资源立刻还给 Windows。

它像一个合租室友——搬进了你的房子(Windows),带来了自己的家具(Linux 文件系统和包管理器),和你共享水电(CPU、内存、网络),但你们各有各的生活空间,互不干扰。

但这个比喻有一个关键点需要修正,而这个关键点恰恰是理解 WSL2 的核心。我们留到概念层再说。

对嵌入式开发者来说,WSL2 最大的吸引力在于:它跑的是真正的 Linux 内核。不是模拟,不是转译,不是兼容层。这意味着你在 WSL2 里编译内核模块、运行 Docker 容器、使用 iptables 配网络——这些行为和在"真正的 Linux"上完全一致。编译工具链、交叉编译、Git 操作,WSL2 全部能胜任。

当然,它也有局限。默认没有完整的 GNOME 桌面(虽然 Windows 11 的 WSLg 可以跑 GUI 程序),网络栈在某些场景下会制造惊喜——踩对了省你三天,踩错了卡你一周,说的就是这个地方。


概念层

WSL2 到底是什么

WSL2 的全称是 Windows Subsystem for Linux 2。名字里有"Subsystem"这个词,但别被它骗了——WSL2 不是 Windows 的一个子系统,而是一个真正的 Linux 内核,运行在微软 Hyper-V 的轻量级虚拟机里。

把它的架构摊开来看。

Windows 本身有一个内核(NT 内核),负责管理你的硬件、进程、文件系统。WSL2 在这个基础上,通过 Hyper-V 技术再启动一个独立的 Linux 内核。这个 Linux 内核是微软从 Linux 官方源码编译的,完整、未删减。

┌──────────────────────────────────────┐
│           Windows 应用程序            │
├──────────────────────────────────────┤
│            Windows NT 内核            │
├───────────────┬──────────────────────┤
│    Hyper-V    │                      │
├───────────────┤   其他 Windows 组件   │
│  Linux 内核    │                      │
│   (WSL2)      │                      │
├───────────────┴──────────────────────┤
│           共享的物理硬件               │
└──────────────────────────────────────┘

两颗内核共享同一台物理机器的 CPU 和内存,但各自管理自己的进程和文件系统。Windows 管 Windows 的,Linux 管 Linux 的。

WSL1 vs WSL2 —— 为什么大版本号变了

你可能听说过 WSL 还有个第一代。WSL1 的思路完全不同:它没有真正的 Linux 内核,而是在 Windows 内核上实现了一套 Linux 系统调用的翻译层。Linux 程序调用 fork(),WSL1 把这个调用翻译成 Windows 的进程创建 API。

这种方案轻量、启动快,但有一个致命问题:翻译不可能 100% 完整。很多 Linux 特有的系统调用、/proc 文件系统、eBPF、Docker 容器——这些东西在 WSL1 上根本跑不了,因为 NT 内核压根没有对应的概念。

WSL2 的方案简单粗暴:不翻译了,直接跑一个真的 Linux 内核。翻译带来的兼容性问题彻底消失——因为根本不需要翻译。

这就是为什么 WSL2 能跑 Docker、能编译内核模块、能用 strace 追踪系统调用,而 WSL1 不行。

回到那个类比

我刚才说 WSL2 像一个合租室友,搬进了你的房子,和你共享水电。这个比喻在"共享硬件资源"这部分是对的——WSL2 确实和 Windows 共享 CPU、内存、磁盘 I/O。

但"合租"这个比喻有一个地方是错的:真正的合租室友共享同一套水电管网——同一个水管、同一个电路。而 WSL2 没有共享 Windows 的"管网"。它带来了自己的一整套基础设施——自己的内核、自己的网络栈、自己的文件系统驱动。Windows 的 NT 内核和 WSL2 的 Linux 内核之间,不是"共享"的关系,而是"毗邻"的关系。它们是两个完全独立的住户,只是恰好在同一栋楼里。

这个区别听起来学术味很浓,但它会直接导致你后面遇到的每一个坑:

  • 为什么 WSL2 的 IP 地址和 Windows 不一样?因为它们各有各的网络栈。
  • 为什么 WSL2 里改了 /etc/resolv.conf,Windows 的 DNS 不受影响?因为它们各有各的 DNS 解析。
  • 为什么从局域网里的其他设备(比如开发板)无法直接访问 WSL2 里跑的服务?因为 WSL2 的网络藏在 Windows 后面,外面看不见。

理解了"毗邻而非共享"这个架构事实,后面关于网络模式、文件系统互访的所有讨论,你都能自己推导出来。


实践层

4.1 检查前提条件

动手之前,先确认你的 Windows 版本够不够格。

Win + R,输入 winver,回车。会弹出一个窗口,上面写着你的 Windows 版本和内部版本号。

要求

  • Windows 10:内部版本 1903 或更高(推荐 2004+)
  • Windows 11:全部支持

如果你用的是 Windows 10 且版本低于 1903——老实说,2024 年了该更新了。Windows 10 的官方支持已经进入倒计时,升到最新版本只有好处没有坏处。

再确认一项:BIOS 里的硬件虚拟化是否开启。WSL2 依赖 CPU 的虚拟化扩展(Intel VT-x 或 AMD-V),如果这个没开,后面所有操作都会报错。

powershell
# 在 PowerShell 中检查虚拟化是否启用
Get-ComputerInfo -Property "HyperV*"

如果输出中 HyperVisorPresentTrue,说明虚拟化已就绪。如果为 False,需要重启进 BIOS,找到 Intel Virtualization Technology(Intel CPU)或 SVM Mode(AMD CPU),设置为 Enabled

4.2 一键安装

WSL2 的安装,在最近几个版本的 Windows 里,已经被简化到了令人发指的程度。

管理员身份打开 PowerShell(右键开始菜单 → 选择"终端管理员"或"Windows PowerShell(管理员)"),然后:

powershell
# 安装 WSL(默认安装 WSL2 + Ubuntu)
wsl --install

就这一行。

它会自动完成四件事:

  1. 启用"适用于 Linux 的 Windows 子系统"功能
  2. 启用"虚拟机平台"功能
  3. 下载并安装 WSL2 的 Linux 内核更新包
  4. 从 Microsoft Store 安装默认的 Ubuntu 发行版

整个过程大约几分钟,取决于你的网速。安装完成后,系统会提示你重启电脑

⚠️ 必须重启 这不是建议,是必须。WSL2 依赖的 Hyper-V 虚拟化平台,在功能启用后需要重启才能生效。跳过重启直接用,你会收获一个报错:WslRegisterDistribution failed with error: 0x8007019e

重启完成后,系统会自动弹出一个终端窗口,提示你为 Ubuntu 创建用户名和密码:

Enter new UNIX username:

输入你想要的用户名(小写英文,比如 dev),然后设置密码。注意——Linux 输入密码时屏幕上不会有任何显示,没有星号,没有圆点,什么都没有。这是正常的安全行为,不是卡住了。闭着眼睛输完,按回车就好。

设置完成后,你会看到命令提示符:

bash
dev@DESKTOP-XXXXXXX:~$

到这里,WSL2 上的 Ubuntu 就装好了。

但等一下—— 如果你安装时遇到了问题,先别急。最常见的原因是 BIOS 中虚拟化没有开启(回到 4.1 检查),或者 Windows 版本不够新。企业环境还有一种情况:Microsoft Store 被组策略禁用了,这时候可以用离线安装方式——在微软官方文档搜索"WSL manual install"找到 appx 离线包。

4.3 安装特定版本的 Ubuntu

默认安装的"Ubuntu"发行版会自动追踪最新的 LTS 版本(目前是 24.04 LTS)。如果你想要特定版本:

powershell
# 查看所有可用的 Linux 发行版
wsl --list --online

输出类似这样:

NAME                                   FRIENDLY NAME
Ubuntu                                 Ubuntu
Ubuntu-22.04                           Ubuntu 22.04 LTS
Ubuntu-24.04                           Ubuntu 24.04 LTS
Debian                                 Debian GNU/Linux
...

安装特定版本:

powershell
# 安装 Ubuntu 22.04 LTS
wsl --install -d Ubuntu-22.04

对于嵌入式开发,Ubuntu 22.04 LTS(Jammy Jellyfish)和 24.04 LTS(Noble Numbat)都是稳妥的选择。22.04 更成熟、社区资源更多;24.04 更新、工具链版本更新。选哪个都不会踩大坑——如果实在选不出来,就用 22.04,这是目前嵌入式教程圈子里用得最多的版本。

4.4 wsl 命令速查

装好之后,你需要知道怎么管理它。以下是日常使用的核心命令,建议在 PowerShell 里逐个试一遍:

powershell
# 启动默认的 Linux 发行版,进入 Shell
wsl

# 启动指定版本
wsl -d Ubuntu-22.04

# 查看已安装的发行版及其状态
wsl --list --verbose
# 预期输出:
#   NAME            STATE           VERSION
# * Ubuntu          Running         2
#   Ubuntu-22.04    Stopped         2

# 设置默认发行版(带 * 号的那个)
wsl --set-default Ubuntu-22.04

# 确保使用 WSL2(不是 WSL1)
wsl --set-default-version 2

# 关闭所有正在运行的 WSL 实例
wsl --shutdown

# 关闭指定发行版
wsl -t Ubuntu-22.04

在 WSL Shell 里想回到 Windows?输入 exit 或直接关闭终端窗口。

有一点值得了解:关闭终端后,WSL2 的 Linux 内核不会立刻停止——它会继续在后台运行,大约 8 分钟无活动后自动回收资源。如果你改了配置文件需要重启 WSL 才生效,用 wsl --shutdown 强制关机。

4.5 网络模式选择——嵌入式开发的关键岔路口

这一节是本章最重要的部分。

还记得概念层里那个类比吗?WSL2 和 Windows 是两个"毗邻的住户"。这就引出了一个实际问题:它们怎么上网?外面的人怎么找到 WSL2?

WSL2 目前有两种网络模式。

NAT 模式(默认)

Windows 充当"路由器",WSL2 藏在 Windows 后面通过地址转换上网。WSL2 有一个内网 IP(通常是 172.x.x.x),Windows 有自己的局域网 IP(比如 192.168.1.100)。WSL2 能访问外网,但局域网里的其他设备——比如你的嵌入式开发板——看不到 WSL2。

互联网 ←→ 路由器 ←→ Windows (192.168.1.100)
                       ↕ NAT
                    WSL2 (172.x.x.x)    ← 开发板看不到这个地址

Mirrored 模式(Windows 11 22H2+)

这是 2023 年微软新增的模式。WSL2 直接"镜像"Windows 的网络接口——和 Windows 用同一套 IP 地址、同一个网络栈。你在 WSL2 里启动一个 HTTP 服务监听 8080 端口,局域网里的开发板直接通过 192.168.1.100:8080 就能访问到。

互联网 ←→ 路由器 ←→ Windows (192.168.1.100)
                       ↕ 镜像(同一套 IP)
                    WSL2 (同样是 192.168.1.100)    ← 开发板直接可达

回到那个合租公寓。现在你应该能看出来了——NAT 模式就像 WSL2 住在 Windows 家的地下室:有自己的房间,能通过 Windows 家的大门出去,但外面的人不知道地下室里住了人。快递(网络请求)只能送到一楼前台(Windows),由前台转交。Mirrored 模式就像 WSL2 和 Windows 合用同一个门牌号:外面的人分不清是谁接的电话,但两个人都能直接和外界打交道。

对于嵌入式开发,我的建议是:如果你用的是 Windows 11,开启 Mirrored 模式。后面我们要通过 TFTP 给开发板传文件、配 NFS 根文件系统——这些操作都需要开发板能直接访问 WSL2 的网络服务。NAT 模式下你需要手动做端口转发,踩坑概率极高。

开启方法:在 Windows 用户目录下创建或编辑 %USERPROFILE%\.wslconfig 文件:

ini
# 文件路径:%USERPROFILE%\.wslconfig
# 即 C:\Users\你的用户名\.wslconfig

[wsl2]
networkingMode=mirrored

保存后,在 PowerShell 中重启 WSL:

powershell
wsl --shutdown
wsl

进入 WSL 后验证:

bash
# 查看网络接口信息
ip addr show eth0
# 在 mirrored 模式下,你会看到和 Windows 相同的局域网 IP

如果你还在用 Windows 10,Mirrored 模式不可用,只能用 NAT。别慌——下一章的虚拟机方案可以补上这个短板。WSL2 和虚拟机不是非此即彼的关系,很多开发者两个都装:日常命令行用 WSL2(轻快),需要完整桌面和网络直连时开虚拟机。

4.6 文件系统互访

两个系统之间的文件互访,是 WSL2 最方便也最容易踩坑的功能之一。

从 Windows 访问 WSL2 的文件

在 Windows 文件资源管理器地址栏里输入 \\wsl$,你会看到以发行版命名的文件夹(比如 Ubuntu)。点进去,就是 WSL2 的完整 Linux 文件系统。

也可以在 WSL Shell 里直接用命令打开:

bash
# 在 Windows 资源管理器中打开 WSL 的当前目录
explorer.exe .

从 WSL2 访问 Windows 的文件

Windows 的 C 盘在 WSL 里挂载在 /mnt/c/

bash
# 查看 Windows 桌面目录
ls /mnt/c/Users/*/Desktop/

但这里有一个性能陷阱。

从 WSL2 访问 /mnt/c/ 的速度,比访问 WSL2 自己的 ~/ 慢很多——有时慢 5 倍以上。原因是 /mnt/c/ 走的是 9P 文件协议,经过了一层转换。

所以,如果你要在 WSL2 里编译代码——比如后面编译内核、编译 U-Boot——一定要把源码放在 WSL2 自己的文件系统里(比如 ~/projects/),而不是放在 /mnt/c/Users/.../ 下面。前者编译飞快,后者会让你等得怀疑人生。


练习题

走到这里,WSL2 的基本使用应该已经清楚了——或者你以为清楚了。 下面几道题难度递进,建议先不看提示独立想,卡住了再翻。

练习 1.1 ⭐(理解)

WSL1 使用系统调用翻译层来运行 Linux 程序,而 WSL2 使用真正的 Linux 内核。请用自己的话解释:为什么 Docker 容器在 WSL1 上无法运行,而在 WSL2 上可以?

提示:Docker 依赖 Linux 内核的 cgroups 和 namespace 特性。翻译层能完全复制这些特性吗?

练习 1.2 ⭐⭐(应用)

在 WSL2 的 Mirrored 网络模式下,你在 WSL2 里启动了一个 HTTP 文件服务器,监听端口 8080。你的嵌入式开发板和 Windows 电脑通过路由器连接在同一个局域网,Windows 的 IP 是 192.168.1.100。请在开发板上写出测试连通性的命令,并说明预期结果。

练习 1.3 ⭐⭐⭐(思考)

有人说:"WSL2 就是一个虚拟机,和 VMware 没什么本质区别。" 你同意吗?请从启动速度、资源管理方式、文件系统集成三个角度,分析 WSL2 和传统虚拟机的异同。


本章回响

本章真正在做的事情,是让你理解 WSL2 的"身份"——它不是一个模拟器,不是一个兼容层,而是一个真正的 Linux 内核,以一种前所未有的方式和 Windows 毗邻共存。

理解了"毗邻而非共享"这个架构之后,WSL2 的很多行为就不再令人困惑了。为什么它有自己的 IP?因为它有独立的网络栈。为什么从 Windows 访问 WSL2 文件要走 \\wsl$?因为它们是两套独立的文件系统。为什么编译代码要放在 ~/ 而不是 /mnt/c/?因为跨文件系统的 9P 协议有性能损耗。这些看似分散的知识点,背后是同一个架构事实。

还记得开头那个问题吗——WSL2 和"真正的 Linux"之间那道看不见的缝隙到底是什么?现在你应该能回答了:那道缝隙不在功能层面——WSL2 跑的是真正的 Linux 内核,系统调用、编译工具链、Docker 全部货真价实。缝隙在网络层面——WSL2 的网络栈被 Windows 包裹着,默认情况下外面的设备看不到它。这扇窗户能不能打开、怎么打开,取决于你选择的网络模式。踩对了(Mirrored 模式),WSL2 就是一台几乎无缝的 Linux 开发机;踩错了(NAT 模式 + 不知道怎么配端口转发),后面做网络调试时会卡得不明不白。

WSL2 是最快的 Linux 入口,但它不是唯一的入口。下一章我们会打开另一扇门——虚拟机方案。它比 WSL2 重,启动慢,占资源——但它给你的是一个完整的 Ubuntu 桌面,一个不受任何限制的 Linux 环境。两条路各有各的场景,很多开发者最终两个都装。我们接着走。


← 专栏首页下一章 →

Built with VitePress