
深入剖析 WSL2 启动流程从 wsl.exe 到 bash 的完整链路【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSLWSL2 的启动是一个横跨 Windows 与 Linux 两个世界、涉及 COM 调用、Hyper-V 虚拟机HCS、hvsocket 通信与多级 Linux init 进程的复杂过程。本文以仓库文档 boot-process.md 为骨架结合 WSL 开源仓库的真实源码逐层拆解从用户在终端敲下wsl.exe到 bash 就绪的每一步涵盖虚拟机配置、mini_init / gns / init / session leader / relay 各进程的职责与消息协议帮助你建立对 WSL2 启动链路的完整认知并能够循着源码路径继续深入阅读。启动流程全景一张序列图看懂整体架构WSL2 的启动并非一条命令启动一个进程那么简单它本质上包含两条独立但又相互依赖的链路Windows 侧wsl.exe命令行入口通过 COM 与运行在会话 0 中的wslservice.exe服务通信由后者负责创建发行版实例、启动 WSL2 虚拟机、维护与 Linux 侧各进程的 hvsocket 通道Linux 侧虚拟机内的mini_init→gns→init→ session leader → relay → 用户进程bash逐级 fork/exec形成一条完整的进程创建链。官方文档用下面的 Mermaid 序列图精确描绘了从wsl.exe调用到 bash 启动的完整事件顺序详见 boot-process.md这条链路中各进程的定位与相互连接还可以参考 index.md 中的组件架构图wslservice.exe通过 hvsocket 同时连接mini_init与gnsmini_init通过 exec 派生出gns、init与localhost而init又会继续 exec 出plan9与 session leader最终由 session leader 派生 relay 去 exec 用户命令。CreateInstance()发行版实例的创建当wslservice.exe通过 COM 接收到CreateInstance()调用时它需要完成三件事详见 wslservice.exe.md 与 boot-process.md1识别目标发行版服务会在 Windows 注册表中查询DistributionRegistration实现见 DistributionRegistration.cpp匹配方式有两种按调用方传入的发行版 ID 精确匹配若未提供 ID则回退使用系统默认发行版。2按发行版类型分派根据发行版是 WSL1 还是 WSL2 走不同路径WSL1无需虚拟机直接在 Windows 侧创建一个 WSL1 实例WSL2需要启动或复用一个 WSL2 虚拟机下文单独展开。3关联实例与调用进程将新创建的发行版实例与发起调用的 Windows 进程进行关联实现见 Lifetime.cpp以便管理该实例的生命周期。值得补充的是wslservice.exe是运行在会话 0、以 SYSTEM 身份运行的 Windows 服务负责管理 WSL 会话、与 WSL2 虚拟机通信以及配置发行版。客户端通过其 COM 接口ILxssUserSession定义见 wslservice.idl与之交互CoCreateInstance()由LxssUserSessionFactory见 LxssUserSessionFactory.cpp处理同一 Windows 用户多次调用会返回同一个LxssUserSession实例见 LxssUserSession.cpp。除CreateInstance()外该接口还提供CreateLxProcess()在发行版内启动进程、RegisterDistribution()注册新发行版、Shutdown()终止全部发行版等关键方法。启动 WSL2 虚拟机HCS 与虚拟机配置 JSON启动 WSL2 发行版的前提是存在一个 WSL2 虚拟机。如果虚拟机尚未运行它会作为CreateInstance()调用的一部分被创建出来。通过 HCS 服务创建虚拟机虚拟机的创建依托 Windows 的 Host Compute SystemHCS服务核心逻辑位于 WslCoreVm.cpp。流程如下wslservice.exe生成一段描述虚拟机配置的JSON 字符串将该 JSON 传给HcsCreateComputeSystem()创建新虚拟机HCS 的 JSON schema 细节可参阅 hcs_schema.h。JSON 配置中的三个关键部分虚拟机配置 JSON 至少包含以下内容见 boot-process.md配置项说明内核kernelWSL 默认使用内置内核通常安装于C:\Program Files\WSL\tools\kernel若用户在.wslconfig中覆盖了kernel配置项则使用自定义内核initramfsWSL 使用自带的 initramfs通常位于C:\Program Files\WSL\tools\initrd.img其中只包含 mini_init 这一个二进制虚拟化资源虚拟机可访问的 CPU、内存RAM、GPU 等资源配额虚拟机启动后会先引导进入上述内核随后执行 initramfs 中的 mini_init——这是 WSL2 虚拟机内的第一个用户态进程也是整个 Linux 侧启动链的起点。Linux 启动过程mini_init 与两级配置消息mini_init虚拟机内的用户态初始化mini_init是 WSL2 虚拟机启动后执行的第一个可执行文件。与标准 Linux init 类似它启动时首先挂载/proc、/sys、/dev等标准挂载点随后执行一系列配置包括启用崩溃转储收集、通过/dev/console配置日志、进行 tty 配置等详见 mini_init.md。一切就绪后mini_init会向wslservice.exe建立两条 hvsocket 通道mini_init 通道用于接收wslservice.exe发来的消息。常见消息包括LxMiniInitMessageLaunchInit挂载虚拟磁盘并启动新发行版、LxMiniInitMessageMount在/mnt/wsl下挂载磁盘用于wsl --mount、EJECT_VHD_MESSAGE弹出磁盘、LxMiniInitMessageImport/LxMiniInitMessageExport导入 / 导出发行版等通知通道用于向wslservice.exe发送通知主要用来上报 Linux 进程的退出事件wslservice据此判断发行版是否已终止。所有消息与响应的完整枚举定义在 lxinitshared.h例如LxMiniInitMessageLaunchInit, // 挂载发行版 VHD 并启动 init LxMiniInitMessageImport, LxMiniInitMessageImportInplace, LxMiniInitMessageExport, LxMiniInitMessageCreateInstanceResult, LxMiniInitMessageEjectVhd, LxMiniInitMessageEarlyConfig, // 早期配置 LxMiniInitMessageInitialConfig, // 初始配置 LxMiniInitMessageMount, LxMiniInitMessageUnmount, ...LxMiniInitMessageEarlyConfig早期配置消息在执行完自身初始化后mini_init会收到wslservice.exe发来的LxMiniInitMessageEarlyConfig消息见 boot-process.md其中携带系统 VHD、交换 VHD 以及如有内核模块 VHD 的标识符虚拟机主机名hostname配置的内存回收模式memory reclaim mode与页上报顺序page reporting order。在源码 main.cpp 的LxMiniInitMessageEarlyConfig处理分支中可以看到该消息的更多实际用途EnableSafeMode会开启安全模式并禁用大量特性IsolateDistroCgroup且宿主支持 cgroup v2 时调用SetupWslUserCgroup()设置用户 cgroup随后建立供 guest 网络服务使用的 hvsocket 连接若启用了 DNS 隧道EnableDnsTunneling还会单独再开一条 hvsocket 连接用于 DNS 隧道。gns网络配置进程收到 EarlyConfig 后mini_init会fork()并exec(/gns)派生 gns 进程负责虚拟机内的网络配置。wslservice.exe通过LxGnsMessageInterfaceConfiguration向gns下发配置gns以LxGnsMessageResult回执结果。WSL2 的网络设置对所有发行版共享。只要 WSL2 在运行gns就与wslservice.exe保持一条 hvsocket 通道用于下发并应用接口 IP 配置、路由表项、DNS 配置、MTU 大小等。当启用 DNS 隧道时gns还负责直接应答 DNS 请求。相关实现可参见 GnsEngine.cppLinux 侧与 GnsChannel.cppWindows 侧。LxMiniInitMessageInitialConfig初始配置消息随后mini_init会收到LxMiniInitMessageInitialConfig消息其中包含见 boot-process.md熵缓冲区entropy buffer用于为虚拟机熵池播种GPU 驱动共享GPU driver shares信息如有则指定需要挂载的 GPU 驱动共享是否启用 wslgWSL 图形界面支持。其他维护任务此外mini_init还承担多项维护任务见 mini_init.md回收未使用的内存对应 EarlyConfig 中的内存回收配置启动调试 shell tty在虚拟机终止时同步 IO调整文件系统大小供wsl --manage distro --resize使用格式化磁盘安装新发行版时使用。在应用完wslservice.exe请求的全部配置之后虚拟机即具备启动 Linux 发行版的条件。启动 Linux 发行版从 LaunchInit 到 session leaderLxMiniInitMessageLaunchInit挂载 VHD 并派生 init要启动一个新的发行版wslservice.exe会向mini_init发送LxMiniInitMessageLaunchInit消息。mini_init随即挂载发行版 VHD并在子命名空间中派生并启动 init详见 init.md。从源码 main.cpp 可以看到这条消息的实际处理逻辑mini_init通过UtilConnectVsock建立到LX_INIT_UTILITY_VM_INIT_PORT的 hvsocket 通道若启用 GUI 应用还会额外连接一条随后调用UtilCreateChildProcess创建名为LaunchDistro的子进程子进程在ProcessLaunchInitMessage中真正完成启动并且创建时使用了如下命名空间克隆标志CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD这正是文档所强调的隔离机制每个 WSL2 发行版都运行在独立的 mount、pid 与 UTS 命名空间中互不可见、可并行运行。具体启动顺序是挂载发行版 VHD → 克隆进子命名空间 → chroot 到 VHD 挂载点 → 执行 init。同时所有发行版共享同一个/mnt/wsl挂载点。init发行版内的顶级进程init是发行版的顶级进程WSL1 下由wslservice直接启动WSL2 下由mini_init启动。启动后init会执行一系列初始化任务见 init.md挂载/proc、/sys、/dev配置 cgroups注册 binfmt 解释器与 interop 相关解析/etc/wsl.conf启动 systemd见 systemd.md挂载 drvfs 驱动器见 drvfs.md配置 wslg。就绪后init建立与wslservice的连接WSL1 走lxbusWSL2 走hvsocket并通过该通道接收命令。从 lxinitshared.h 的枚举可以看到完整命令集例如LxInitMessageCreateProcess, // 创建用户进程WSL1 路径 LxInitMessageCreateSession, // 创建新的 session leader LxInitMessageCreateSessionResponse, LxInitMessageNetworkInformation, LxInitMessageInitialize, // 配置发行版 LxInitMessageCreateProcessUtilityVm, // 创建用户进程WSL2 路径 LxInitMessageExitStatus, // 进程退出状态上报 LxInitMessageWindowSizeChanged, // 终端窗口尺寸变化 LxInitMessageTerminateInstance, // 终止发行版 ...LxInitMessageCreateSession在 init.cpp 中处理initfork()出一个 session leader并向wslservice.exe回送LxInitMessageCreateSessionResponse。session leader面向用户进程的创建者session leader 是收到LxInitMessageCreateSession消息后从initfork 出来的 Linux 进程见 session-leader.md 与 init.cpp每个 session leader 与一个 Windows 控制台console关联代表用户创建 Linux 进程。创建用户进程时wslservice.exe发送LxInitMessageCreateProcessWSL1或LxInitMessageCreateProcessUtilityVmWSL2消息消息中携带命令行、当前目录、环境变量、用户名等。两条路径的实现略有差异WSL1 路径session leader 直接fork()子进程在exec()进入用户 Linux 进程前先配置好 uid/gid、当前目录以及 stdin/stdout/stderr 标准文件描述符WSL2 路径session leaderfork()出 relay 进程由 relay 负责创建用户进程并把输出中继回wsl.exe。中继 Linux 进程的输入输出到 WindowsCreateLxProcess 返回的五个句柄用户进程创建成功后wslservice.exe从CreateLxProcess()返回给wsl.exe。在 WSL2 场景下wsl.exe会收到以下 HANDLES见 boot-process.md句柄用途STDIN向 Linux 进程写入标准输入STDOUT读取 Linux 进程的标准输出STDERR读取 Linux 进程的标准错误Control channel通知 Linux 进程终端变化如wsl.exe终端窗口被调整大小时并将变化应用到 Linux 进程Interop channel双向用途见下relayWSL2 的中继进程WSL2 下真正承担中继工作的是 relay 进程。它由 session leader 在收到LxInitMessageCreateProcessUtilityVm消息后创建随后与wslservice.exe建立多条 hvsocket 通道分别用于中继标准文件描述符stdin / stdout / stderr中继终端信息如 Windows 侧窗口尺寸变化向 Windows 通知 Linux 进程的退出。通道就绪后relayfork()成两个进程父进程负责读写子进程的标准文件描述符并中继给 Windows子进程调用exec()启动用户进程本例中为/bin/bash。随后wsl.exe与 relay 之间全双工中继 STDIN / STDOUT / STDERR——这正是你在终端里与 bash 交互的物理通道。STDIN / STDOUT / STDERR 的中继逻辑STDIN、STDOUT、STDERR三个句柄用于把 Linux 进程的输入输出中继到 Windows 终端。关键点在于句柄类型不同终端、管道、文件等wsl.exe会套用不同的中继逻辑以达成 Windows 与 Linux 之间最好的兼容性。这部分逻辑集中在 relay.cppWindows 侧中继实现注意与 Linux 侧的 relay 进程区分。Control channel 与 Interop channelControl channel用于把终端变化通知给 Linux 进程——典型场景是wsl.exe终端窗口被 resize 时变化会经由该通道同步应用到 Linux 进程对应 lxinitshared.h 中的LxInitMessageWindowSizeChanged消息。Interop channel有两种用途从 Linux 创建 Windows 进程——即 WSL 的双向互操作能力详见 interop.md通知wsl.exeLinux 进程已退出——通过LxInitMessageExitStatus消息传递退出码。进程退出与 wslhost.exe 接管当 Linux 进程退出后relay 通过waitpid()回收子进程并向wsl.exe发送LxInitMessageExitStatus进程退出码wsl.exe收到后刷新剩余 IO并以与 Linux 进程相同的退出码退出自身——这正是 WSL 命令的退出码能够无缝传递给 Windows 脚本的原因。还有一个值得注意的边界场景如果wsl.exe在 Linux 进程退出之前被终止例如用户直接关闭了终端窗口wslhost.exe 会接管 Interop channel继续处理执行 Windows 进程的请求避免正在运行的 Linux 进程因宿主进程消失而失去互操作能力。附关键源码路径速查关注点仓库路径消息与响应枚举mini_init / init / gns 全部消息src/shared/inc/lxinitshared.hmini_init消息处理LaunchInit / EarlyConfig / InitialConfig 等src/linux/init/main.cppinit的 session 与进程创建src/linux/init/init.cpp网络配置Linux 侧src/linux/init/GnsEngine.cpp发行版注册表查询src/windows/service/exe/DistributionRegistration.cpp实例生命周期关联src/windows/service/exe/Lifetime.cppWSL2 虚拟机管理src/windows/service/exe/WslCoreVm.cppHCS JSON schemasrc/windows/common/hcs_schema.hWindows 侧 IO / 终端中继逻辑src/windows/common/relay.cppCOM 服务与会话src/windows/service/exe/LxssUserSession.cppWSL 架构总览doc/docs/technical-documentation/index.md至此从用户敲下wsl.exe到 bash 提示符出现的完整链路已经清晰wsl.exe通过 COM 驱动wslservice.exe后者借 HCS 拉起承载 mini_init 的虚拟机mini_init 通过两级配置消息完成环境准备并派生 gns 与 initinit 创建 session leadersession leader 再经由 relay 把用户进程接入 Windows 的终端 IO。理解这条链路是进一步研究 WSL 网络、互操作、systemd 集成与调试疑难问题的坚实基础。【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考