The WSL2 boot process

This page describes the steps in the WSL2 process, from the user invoking wsl.exe to the user's Linux shell (bash in this example), in the WSL2 distribution.

Overview

The below diagram shows the sequence of event to start bash within a WSL2 distribution. See WSL architecture for details about what each process does.

sequenceDiagram wsl.exe->>wslservice.exe: CreateInstance(<distro>) wslservice.exe->>wsl.exe: S_OK wsl.exe->>wslservice.exe: CreateLxProcess(<distro>, <command line>, <env>, ...) create participant mini_init wslservice.exe->>mini_init: LxMiniInitMessageEarlyConfig create participant gns mini_init-->>gns: fork(), exec("/gns") wslservice.exe->>gns: LxGnsMessageInterfaceConfiguration gns->>wslservice.exe: LxGnsMessageResult wslservice.exe->>mini_init: LxMiniInitMessageInitialConfig wslservice.exe->>mini_init: LxMiniInitMessageLaunchInit create participant init mini_init-->>init: fork(), exec("/init") init->>wslservice.exe: LxMiniInitMessageCreateInstanceResult wslservice.exe->>init: LxInitMessageCreateSession create participant session leader init-->>session leader: fork() session leader->>wslservice.exe: LxInitMessageCreateSessionResponse wslservice.exe->>session leader: InitCreateProcessUtilityVm create participant relay session leader-->>relay: fork() relay->>wslservice.exe: LxMessageResultUint32 (hvsocket connect port) wslservice.exe->>relay: connect hvsockets for STDIN, STDOUT, STDERR create participant bash relay-->>bash: fork(), exec("/bin/bash") relay<<-->>bash: relay STDIN, STDOUT, STDERR wslservice.exe-->>wsl.exe: S_OK + hvsockets for STDIN, STDOUT, STDERR wsl.exe<<->>relay: Relay STDIN, STDOUT, STDERR destroy bash relay-->>bash: waitpid() relay->>wsl.exe: LxInitMessageExitStatus (process exit code)

CreateInstance()

When wslervice.exe receives the CreateInstance() call via COM, it will:

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.

2) Based on the type of distribution (WSL1 or WSL2), either create a WSL1 instance, or start up a WSL2 virtual machine.

3) Associate the newly creating distribution to the calling process (see src/windows/service/exe/Lifetime.cpp)

Starting the WSL2 virtual machine

To start a WSL2 distribution, wslservice.exe needs a virtual machine. If the virtual machine isn't already running, it will be created as part of the CreateInstance() call.

The WSL2 virtual machine is created via the Host Compute System (HCS) service (see src/windows/service/exe/WslCoreVm.cpp).

To create a new virtual machine, wslservice.exe generates a JSON string, which describes the virtual machine configuration. This JSON is then passed to HcsCreateComputeSystem() to create a new virtual machine.

See src/windows/common/hcs_schema.h for more details on the HCS JSON schema.

Part of the JSON configuration includes:

  • The kernel: WSL will use its built-in kernel, usually installed C:/Program Files/WSL/tools/kernel, or a custom kernel if overridden via .wslconfig
  • 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 binary
  • The resources accessible to the virtual machine such as CPU, RAM, GPU, etc

When started, the virtual machine will boot into the provided kernel, and then execute mini_init.

The Linux boot process

mini_init 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 which contains the following information:

  • Identifiers for the system VHD, swap VHD and kernel modules VHD if any
  • The machine's hostname
  • The configured memory reclaim mode and page reporting order(See wsl2.pageReporting)*

mini_init then creates the gns process, which is responsible for networking configuration and then receives a LxMiniInitMessageInitialConfig message, which contains:

  • An entropy buffer, to seed the virtual machine's entropy
  • Information about the GPU drivers shares to mount, if any
  • Wether wslg is enabled

After applying all the configuration requested by wslservice.exe, the virtual machine is ready to start Linux distributions.

Starting a Linux distribution

To start a new distribution, wslservice.exe sends a LxMiniInitMessageLaunchInit message to mini_init, which then mounts the distribution vhd and starts init. See (init for more details on WSL2 distributions configuration)

Once running, wslservice.exe can then send a LxInitMessageCreateSession message to start a new session leader inside that distribution, which can be used to launch linux processes

Relaying the linux process's input and output to Windows

Once the user's linux process has been created, wslservice.exe can return from CreateLxProcess() back to wsl.exe. In the case of WSL2, wsl.exe receives the following HANDLES:

  • STDIN
  • STDOUT
  • STDERR
  • Control channel
  • Interop channel

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 will apply different relaying logics (see src/windows/common/relay.cpp) to achieve the best compatibility between Windows & Linux.

The Control channel is used to notify the linux process of a change in the terminal (for instance when wsl.exe's terminal window is resized) so these changes can be applied to the Linux process as well.

The Interop channel has two usages:

  • Create Windows processes from Linux (see interop)
  • Notify wsl.exe when the Linux process has exited (see LxInitMessageExitStatus)

Once the Linux process has exited, wsl.exe flushes all remaining IO, and exits with the same exit code as the Linux process.

If wsl.exe is terminated before the Linux process exits, wslhost.exe will take over the Interop channel and continue to handle requests to execute Windows processes.