微软重构WSL 全新架构更稳定:内存跑爆,也不再全盘失联
微软重构WSL 全新架构更稳定:内存跑爆,也不再全盘失联 在 WSL 里编译过大型项目的人,多少都见过这种场面: 内存一路冲到顶。 编译器先挂,终端随后失联,systemd 没反应,连重新进入发行版都做不到。 项目编译失败还能再来。 可整个 WSL 被一起拖下水,最后只能执行 wsl --
💡 你将学到
微软重构WSL 全新架构更稳定:内存跑爆,也不再全盘失联 在 WSL 里编译过大型项目的人,多少都见过这种场面: 内存一路冲到顶。 编译器先挂,终端随后失联,systemd 没反应,连重新进入发行版都做不到。 项目编译失败还能再来。 可整个 WSL 被一起拖下水,最后只能执行 wsl --
📜 目录
微软重构WSL 全新架构更稳定:内存跑爆,也不再全盘失联
在 WSL 里编译过大型项目的人,多少都见过这种场面:
内存一路冲到顶。
编译器先挂,终端随后失联,systemd 没反应,连重新进入发行版都做不到。
项目编译失败还能再来。
可整个 WSL 被一起拖下水,最后只能执行 wsl --shutdown 强制重启,这就有点离谱了。
微软终于开始收拾这个老问题。
WSL 项目正式合并了 #40519 号更新。整个改动包含 49 次提交,修改 13 个文件,新增 498 行代码。
一句话概括:
微软给WSL装了一根“资源保险丝”。
以后某个 Linux 任务把内存吃光,可以让任务自己倒下,尽量别把整个 WSL 一起带走。
01. 以前的WSL,一出事就容易“全楼停电”
这次修改背后,有一个真实故障案例。
一名用户在 Ubuntu 24.04 中编译 Vulkan SDK。编译负载上来后,WSL 直接异常退出,随后反复出现启动失败和连接失败。
真正麻烦的地方,在于 WSL 以前的资源边界不够清晰。
编译器、构建工具、systemd,以及 WSL 自己的关键后台进程,都可能参与同一场资源争夺。
一旦内存被吃光,Linux 会触发 OOM。
OOM Killer 开始挑选进程清理时,WSL 的核心服务也有可能遭殃。
其中包括:
- 管理发行版生命周期的
mini_init - 负责网络服务的 GNS
- 负责文件互操作的 Plan9
- WSL 自己的初始化进程
这就像一栋大楼用电过载。
住户空调开太猛,结果电梯、门禁和消防泵一起断电。就算住户后来关了空调,大楼也不一定能马上恢复运转。
所以很多用户会发现:
内存压力已经过去了,WSL 依旧像被打晕一样,怎么敲都没有反应。
02. 32MiB内存,成了WSL最后一口气
微软这次的做法很干脆。
WSL 启动后,会创建一个名为 /wsl-user 的控制组。
用户启动的编译任务、systemd、Shell 会话和其他工作负载,都会被装进这个受限制的“资源沙箱”。
WSL 自己的关键进程,则留在外面的根控制组。
两边正式分家。
按照合并后的代码,微软会给核心进程强制留下两样资源:
- 32MiB内存
- 0.01个逻辑CPU核心
举个例子。
如果你的 WSL 虚拟机拥有 8GiB 内存,那么 /wsl-user 里的任务最多可以使用大约 8160MiB。
剩下的 32MiB,不准碰。
CPU 也是同样的逻辑。
如果 WSL 能使用 8 个逻辑核心,用户任务最多大约吃到 7.99 核。最后那点调度能力,会留给 WSL 的后台服务。
看上去抠得要命。
可到了所有核心都被编译线程围殴、内存也被吃干抹净的时候,这一点资源可能就是救命的。
当 /wsl-user 撞上内存上限,cgroup 内部会触发 OOM 处理。
被清理的对象会被限制在用户工作负载里面,WSL 的初始化、网络和文件服务不用再陪着一起上路。
需要说明的是,被杀掉的不一定刚好是最先抢内存的程序。
Linux 仍会根据 OOM 评分选择目标。
但故障已经被关进笼子里。
牛马进程可以倒,负责开门和拉闸的人必须活着。
03. 多个Linux发行版,终于不用抢一个停车位
这次更新还解决了另一个隐蔽问题。
很多开发者会同时运行 Ubuntu、Debian、Kali,甚至专门准备多个发行版做测试。
以前,这些发行版启用 systemd 后,可能共享同一套 cgroup 路径。
结果就像几辆车同时抢一个停车位。
一个发行版成功创建 systemd 用户会话,另一个可能直接提示“设备或资源忙”,甚至启动失败。
新架构给每个发行版单独划了地盘:
/
└─ wsl-user
├─ non-distro
├─ distro-发行版A
│ ├─ systemd
│ └─ non-systemd
└─ distro-发行版B
├─ systemd
└─ non-systemd
Ubuntu 有 Ubuntu 的 cgroup。
Debian 有 Debian 的 cgroup。
systemd 和普通进程还会继续分层,启动、关闭和清理互不撞车。
对于只运行一个发行版的用户,这项变化可能没什么感觉。
但对多发行版开发、容器测试和复杂 Linux 环境来说,这算是补上了一块长期欠账。
04. 老项目先别急着真香,cgroup v1可能翻车
新方案建立在 cgroup v2 之上。
这意味着,一些依赖 cgroup v1 的老容器、脚本和内部开发环境,可能遇到兼容性问题。
微软留了一个后门。
如果你的业务必须使用 cgroup v1,可以打开 Windows 用户目录下的 .wslconfig,加入:
[wsl2]
isolateDistroCgroup=false
然后执行:
wsl --shutdown
重新启动发行版后,配置才会生效。
不过这相当于主动拆掉新保险丝。
发行版级 cgroup 隔离、用户任务资源限制,以及多发行版 systemd 隔离,都会被绕过去。
普通用户不用折腾这个选项。
只有明确知道自己的项目依赖 cgroup v1,才值得关闭。
还有一个容易被忽略的细节:
PR 已经合并,不代表稳定版用户现在就能用上。
目前 GitHub 上最新稳定版仍是 6 月 26 日发布的 WSL 2.7.10,时间早于这次代码合并。
微软还需要发布包含这项修改的新版本。
等新版本上线后,再通过下面的命令更新:
wsl --update
05. 谁会最先吃到这波红利?
如果你平时只用 WSL 跑几条 Linux 命令,这次变化很难让你产生明显感觉。
真正受益的,是下面这些重负载场景:
- 编译 Chromium、LLVM、Vulkan SDK 等大型项目
- 运行高并发构建和自动化测试
- 在 WSL 中使用 Docker 或本地数据库
- 跑数据分析、本地模型和高内存任务
- 同时启动多个启用 systemd 的发行版
以前这些任务一旦失控,可能把整个 WSL 拖进黑洞。
新机制上线后,最坏结果更可能收缩为某个进程被杀、某次编译失败。
终端、网络和其他发行版还有机会继续工作。
不过别把它当成“内存增大黑科技”。
32MiB 的保留资源不会让编译速度更快,也不会凭空给电脑增加内存。
.wslconfig 里的 memory、processors 和 swap 仍然需要合理配置。
这次升级解决的重点,是故障发生后的边界。
还有一点要说清楚。
它主要保护 WSL 虚拟机内部的关键进程,降低 WSL 全局失联的概率。Windows 蓝屏、驱动崩溃和宿主机硬件故障,并不在这次修复范围内。
06. 微软终于想明白:功能再多,也得先学会活下来
过去几年,WSL 一直在猛堆功能。
systemd、GPU 计算、Linux 图形应用、镜像网络,一个接一个往上加。
功能确实越来越强。
可一个开发平台是否成熟,不能只看顺风局里能跑多少东西。
真正拉开差距的,是压力打满以后,它能不能控制故障范围,能不能自己爬起来,能不能让用户少敲一次 wsl --shutdown。
微软最初讨论过为系统进程保留 128MiB,最后压到了 32MiB。
这个数字够不够,还得等正式版本上线后接受真实负载轰炸。
但这次方向完全正确。
能在正常情况下运行,只能说明功能做出来了。
能在内存爆仓、CPU 满载和多个发行版同时启动时,依旧保住核心服务,这才开始有生产工具的样子。
说得更直接一点:
这项看不见的底层改动,比再给WSL塞十个花哨功能更值钱。
你在 WSL 里遇到过编译爆内存后彻底失联吗?
如果让你二选一,你更想要极限性能,还是愿意牺牲一点资源,换整个 WSL 不被拖死?
参考资料:
- WSL PR #40519:https://github.com/microsoft/WSL/pull/40519
- 编译导致 WSL 异常退出的问题:https://github.com/microsoft/WSL/issues/40458
- WSL 高级配置说明:https://learn.microsoft.com/zh-cn/windows/wsl/wsl-config
本站文章由编辑人工撰写,收录的工具均经过实测或公开资料核验。文中链接指向工具官网或 GitHub 仓库,仅作信息参考,不构成付费推广。
