| 1 | # The WSL2 boot process |
| 2 | |
| 3 | This page describes the steps in the WSL2 process, from the user invoking [wsl.exe](wsl.exe.md) to the user's Linux shell (bash in this example), in the WSL2 distribution. |
| 4 | |
| 5 | ## Overview |
| 6 | |
| 7 | The below diagram shows the sequence of events to start bash within a WSL2 distribution. See [WSL architecture](index.md) for details about what each process does. |
| 8 | |
| 9 | ```mermaid |
| 10 | sequenceDiagram |
| 11 | wsl.exe->>wslservice.exe: CreateInstance(<distro>) |
| 12 | wslservice.exe->>wsl.exe: S_OK |
| 13 | wsl.exe->>wslservice.exe: CreateLxProcess(<distro>, <command line>, <env>, ...) |
| 14 | create participant mini_init |
| 15 | wslservice.exe->>mini_init: LxMiniInitMessageEarlyConfig |
| 16 | create participant gns |
| 17 | mini_init-->>gns: fork(), exec("/gns") |
| 18 | wslservice.exe->>gns: LxGnsMessageInterfaceConfiguration |
| 19 | gns->>wslservice.exe: LxGnsMessageResult |
| 20 | wslservice.exe->>mini_init: LxMiniInitMessageInitialConfig |
| 21 | wslservice.exe->>mini_init: LxMiniInitMessageLaunchInit |
| 22 | create participant init |
| 23 | mini_init-->>init: fork(), exec("/init") |
| 24 | init->>wslservice.exe: LxMiniInitMessageCreateInstanceResult |
| 25 | wslservice.exe->>init: LxInitMessageCreateSession |
| 26 | create participant session leader |
| 27 | init-->>session leader: fork() |
| 28 | session leader->>wslservice.exe: LxInitMessageCreateSessionResponse |
| 29 | wslservice.exe->>session leader: InitCreateProcessUtilityVm |
| 30 | create participant relay |
| 31 | session leader-->>relay: fork() |
| 32 | relay->>wslservice.exe: LxMessageResultUint32 (hvsocket connect port) |
| 33 | wslservice.exe->>relay: connect hvsockets for STDIN, STDOUT, STDERR |
| 34 | create participant bash |
| 35 | relay-->>bash: fork(), exec("/bin/bash") |
| 36 | relay<<-->>bash: relay STDIN, STDOUT, STDERR |
| 37 | wslservice.exe-->>wsl.exe: S_OK + hvsockets for STDIN, STDOUT, STDERR |
| 38 | wsl.exe<<->>relay: Relay STDIN, STDOUT, STDERR |
| 39 | destroy bash |
| 40 | relay-->>bash: waitpid() |
| 41 | relay->>wsl.exe: LxInitMessageExitStatus (process exit code) |
| 42 | ``` |
| 43 | |
| 44 | ## CreateInstance() |
| 45 | |
| 46 | When [wslservice.exe](wslservice.exe.md) receives the CreateInstance() call via COM, it will: |
| 47 | |
| 48 | 1) Identify which distribution the user wants to create. This is done by looking up the `DistributionRegistration` (see `src/windows/service/exe/DistributionRegistration.cpp`) in the Windows registry, matching either on the distribution ID, or using the default if none is provided. |
| 49 | |
| 50 | 2) Based on the type of distribution (WSL1 or WSL2), either create a WSL1 instance, or start up a WSL2 virtual machine. |
| 51 | |
| 52 | 3) Associate the newly creating distribution to the calling process (see `src/windows/service/exe/Lifetime.cpp`) |
| 53 | |
| 54 | |
| 55 | ## Starting the WSL2 virtual machine |
| 56 | |
| 57 | To start a WSL2 distribution, [wslservice.exe](wslservice.exe.md) needs a virtual machine. If the virtual machine isn't already running, it will be created as part of the `CreateInstance()` call. |
| 58 | |
| 59 | The WSL2 virtual machine is created via the [Host Compute System (HCS) service](https://learn.microsoft.com/virtualization/api/hcs/overview) (see `src/windows/service/exe/WslCoreVm.cpp`). |
| 60 | |
| 61 | To create a new virtual machine, [wslservice.exe](wslservice.exe.md) generates a JSON string, which describes the virtual machine configuration. This JSON is then passed to [HcsCreateComputeSystem()](https://learn.microsoft.com/virtualization/api/hcs/reference/hcscreatecomputesystem) to create a new virtual machine. |
| 62 | |
| 63 | See `src/windows/common/hcs_schema.h` for more details on the HCS JSON schema. |
| 64 | |
| 65 | Part of the JSON configuration includes: |
| 66 | |
| 67 | - The kernel: WSL will use its built-in kernel, usually installed in `C:\Program Files\WSL\tools\kernel`, or a custom kernel if overridden via [.wslconfig](https://learn.microsoft.com/windows/wsl/wsl-config) |
| 68 | - The initramfs: WSL uses its own initramfs (usually installed in `C:\Program Files\WSL\tools\initrd.img`). It's an image that only contains the [mini_init](mini_init.md) binary |
| 69 | - The resources accessible to the virtual machine such as CPU, RAM, GPU, etc |
| 70 | |
| 71 | When started, the virtual machine will boot into the provided kernel, and then execute [mini_init](mini_init.md). |
| 72 | |
| 73 | ## The Linux boot process |
| 74 | |
| 75 | [mini_init](mini_init.md) is the process that performs usermode initialization inside the virtual machine. After performing various configurations, `mini_init` receives a `LxMiniInitMessageEarlyConfig` message from the [wslservice.exe](wslservice.exe.md) which contains the following information: |
| 76 | |
| 77 | - Identifiers for the system VHD, swap VHD and kernel modules VHD if any |
| 78 | - The machine's hostname |
| 79 | - The configured memory reclaim mode and page reporting order |
| 80 | |
| 81 | [mini_init](mini_init.md) then creates the [gns process](gns.md), which is responsible for networking configuration and then receives a `LxMiniInitMessageInitialConfig` message, which contains: |
| 82 | |
| 83 | - An entropy buffer, to seed the virtual machine's entropy |
| 84 | - Information about the GPU drivers shares to mount, if any |
| 85 | - Whether [wslg](https://github.com/microsoft/wslg) is enabled |
| 86 | |
| 87 | After applying all the configuration requested by [wslservice.exe](wslservice.exe.md), the virtual machine is ready to start Linux distributions. |
| 88 | |
| 89 | ## Starting a Linux distribution |
| 90 | |
| 91 | To start a new distribution, [wslservice.exe](wslservice.exe.md) sends a `LxMiniInitMessageLaunchInit` message to [mini_init](mini_init.md), which then mounts the distribution vhd and starts [init](init.md). See [init](init.md) for more details on WSL2 distributions configuration. |
| 92 | |
| 93 | Once running, [wslservice.exe](wslservice.exe.md) can then send a `LxInitMessageCreateSession` message to start a new [session leader](session-leader.md) inside that distribution, which can be used to launch Linux processes |
| 94 | |
| 95 | ## Relaying the Linux process's input and output to Windows |
| 96 | |
| 97 | Once the user's Linux process has been created, [wslservice.exe](wslservice.exe.md) can return from `CreateLxProcess()` back to [wsl.exe](wsl.exe.md). In the case of WSL2, [wsl.exe](wsl.exe.md) receives the following HANDLES: |
| 98 | |
| 99 | - STDIN |
| 100 | - STDOUT |
| 101 | - STDERR |
| 102 | - Control channel |
| 103 | - Interop channel |
| 104 | |
| 105 | The `STDIN`, `STDOUT` and `STDERR` handles are used to relay input and output from the Linux process to the Windows terminal. Depending on the type of handle (terminal, pipe, file, ...), [wsl.exe](wsl.exe.md) will apply different relaying logics (see `src/windows/common/relay.cpp`) to achieve the best compatibility between Windows & Linux. |
| 106 | |
| 107 | The `Control channel` is used to notify the Linux process of a change in the terminal (for instance when [wsl.exe's](wsl.exe.md) terminal window is resized) so these changes can be applied to the Linux process as well. |
| 108 | |
| 109 | The `Interop channel` has two usages: |
| 110 | |
| 111 | - Create Windows processes from Linux (see [interop](interop.md)) |
| 112 | - Notify [wsl.exe](wsl.exe.md) when the Linux process has exited (see `LxInitMessageExitStatus`) |
| 113 | |
| 114 | Once the Linux process has exited, [wsl.exe](wsl.exe.md) flushes all remaining IO, and exits with the same exit code as the Linux process. |
| 115 | |
| 116 | If [wsl.exe](wsl.exe.md) is terminated before the Linux process exits, [wslhost.exe](wslhost.exe.md) will take over the `Interop channel` and continue to handle requests to execute Windows processes. |