1. Project Overview & Quickstart (microsoft/WSL)
File: README.md
Welcome to the Windows Subsystem for Linux (WSL) repository
Learn more about WSL | Downloads & Release notes | Contributing to WSL
About
Windows Subsystem for Linux (WSL) is a powerful way for you to run your Linux command-line tools, utilities and applications, all unmodified and directly on Windows without the overhead of a traditional virtual machine or dual boot setup.
You can install WSL right away by running this command inside of your Windows command line:
wsl --installYou can learn more about best practices for setup, overviews of WSL and more at our WSL documentation page.
Related repositories
WSL also has related open source repositories:
- microsoft/WSL2-Linux-Kernel - The Linux kernel shipped with WSL
- microsoft/WSLg - Support for Linux GUI apps in WSL
- microsoftdocs/wsl - WSL documentation at aka.ms/wsldocs
Contributing
This project welcomes contributions of all types, including coding features / bug fixes, documentation fixes, design proposals and more.
We ask that before you start working on a contribution, please read our Contributor's Guide.
For guidance on developing for WSL, please read the developer docs for instructions on how to build WSL from source and details on its architecture.
Code of Conduct
This project has adopted the Microsoft Open Source Code of Conduct
Trademarks
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoftβs Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-partyβs policies.
Privacy and telemetry
The application logs basic diagnostic data (telemetry). For more information on privacy and what we collect, see our data and privacy documentation.
The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoftβs privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices.
File: doc/docs/technical-documentation/boot-process.md
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 events 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 wslservice.exe receives the CreateInstance() call via COM, it will:
Identify which distribution the user wants to create. This is done by looking up the
DistributionRegistration(seesrc/windows/service/exe/DistributionRegistration.cpp) in the Windows registry, matching either on the distribution ID, or using the default if none is provided.Based on the type of distribution (WSL1 or WSL2), either create a WSL1 instance, or start up a WSL2 virtual machine.
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 in
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
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
- Whether 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.
File: doc/docs/technical-documentation/drvfs.md
Accessing Windows drives from Linux
WSL offers mountpoints to access Windows drives from Linux. These mountpoints are mounted under /mnt by default, and point to the root of Windows drives.
Elevated vs non-elevated mountpoints
Within a distribution, WSL separates between Linux processes that have been created from an elevated (as in administrator level) and from a non-elevated (user level) context.
This is done by having two separate mount namespaces within the distribution. One of them offers an elevated access to Windows drives, and the other offers a non-elevated access to Windows drives.
When a Linux process is created, wslservice.exe determines its elevation status, and then tells init to create the process in the appropriate mount namespace.
Mounting a Windows drive
*Note: This section only applies to WSL2 distributions. *
When a session leader is created, wslservice.exe starts a plan9 file server. This file server can be connected to from the WSL2 virtual machine to mount Windows drives.
When the WSL distribution is created, wslservice.exe uses the LX_INIT_CONFIGURATION_INFORMATION message to indicate whether the process that created the distribution is elevated or not. Based on this, init will mount either the elevated, or un-elevated version of the plan9 server.
Later when the first command is created in the namespace that hasn't been mounted yet, (either elevated, or non-elevated), wslservice.exe sends a LxInitMessageRemountDrvfs to init, which tells init to mount the other namespace.
See: src/windows/service/exe/WslCoreInstance.cpp and src/linux/drvfs.cpp.
Mounting a drive from Linux
As long as the Windows plan9 server is running, drives can be mounted simply by calling mount. For instance mounting the C: drive manually can be done via:
mount -t drvfs C: /tmp/my-mount-pointInternally, this is handled by /usr/sbin/mount.drvfs, which is a symlink to /init. When /init starts, it looks at argv[0] to determine which entrypoint to run. If argv[0] is mount.drvfs, then /init runs the mount.drvfs entrypoint (see MountDrvfsEntry() in src/linux/init/drvfs.cpp).
Depending on the distribution configuration, mount.drvfs will either mount the drive as drvfs (WSL1), or plan9, virtio-plan9 or virtiofs (WSL), depending on .wslconfig.
File: doc/docs/technical-documentation/gns.md
GNS
gns is a process created by mini_init. Its job is to configure networking within the WSL2 virtual machine.
Networking configuration
Networking settings are shared by all WSL2 distributions. While WSL2 is running, gns maintains an hvsocket channel to wslservice.exe, which is used to send various networking related configurations such as:
- Interface IP configuration
- Routing table entries
- DNS configuration
- MTU size configuration
When DNS tunneling is enabled, gns is also responsible for replying to DNS requests.
See src/linux/init/GnsEngine.cpp and src/windows/service/exe/GnsChannel.cpp
File: doc/docs/technical-documentation/index.md
WSL Overview
WSL is comprised of a set of executables, APIs and protocols. This page offers an overview of the different components, and how they're connected.
Click on any component to get more details.
%%{ init: {
'flowchart': { 'curve': 'stepBefore' },
'theme': 'neutral'
}
}%%
graph
subgraph Windows["**Windows**"]
C:\Windows\System32\wsl.exe["C:\Windows\System32\wsl.exe"]---|"CreateProcess()"|wsl.exe;
wsl.exe[[wsl.exe](wsl.exe)]---|COM|wslservice.exe;
wslg.exe[[wslg.exe](wslg.exe)]---|COM|wslservice.exe;
wslconfig.exe[[wslconfig.exe](wslconfig.exe)]---|COM|wslservice.exe;
wslapi.dll[[wslapi.dll](https://learn.microsoft.com/windows/win32/api/wslapi/)]---|COM|wslservice.exe;
id[debian.exe, ubuntu.exe, ]---|"LoadLibrary()"|wslapi.dll;
wslservice.exe[[wslservice.exe](wslservice.exe)]---|"CreateProcessAsUser()"|wslrelay.exe[[wslrelay.exe](wslrelay.exe)];
wslservice.exe---|"CreateProcessAsUser()"|wslhost.exe[[wslhost.exe](wslhost.exe)];
fs["Windows filesystem (//wsl.localhost)"]
end
wslservice.exe -----|hvsocket| mini_init
wslservice.exe -----|hvsocket| gns
fs---|hvsocket|plan9
wsl.exe---|hvsocket|relay
subgraph Linux["**Linux**"]
mini_init[[mini_init](mini_init)]---|"exec()"|gns[[gns](gns)]
mini_init---|"exec()"|init[[init](init)];
mini_init---|"exec()"|localhost[[localhost](localhost)];
subgraph "Linux Distribution"["**Linux Distribution**"]
init[[init](init)]---|"exec()"|plan9[[plan9](plan9)];
init---|"exec()"|sid[session leader];
sid[[session leader](session-leader)]---|"exec()"|relay
relay[[relay](relay)]---|"exec()"|cid["User command (bash, curl)"]
end
endFile: doc/docs/technical-documentation/init.md
Init
Init is top level process of a WSL distribution. For WSL1 distributions, it is launched by wslservice (see src/windows/service/LxssInstance.cpp) and for WSL2 distributions, it is launched by mini_init.
WSL2 specific distributions startup
Each WSL2 distributions runs in a separate mount, pid and UTS namespace. This allows distributions to run in parallel, without "seeing" each other.
When a WSL2 distribution starts, mini_init:
- Mounts the distribution VHD
- Clones into a child namespace
- Chroots in the VHD mountpoint
- Executes init (see the
LxMiniInitMessageLaunchInitmessage).
While each distribution runs in its own mount namespace, the /mnt/wsl mountpoint is shared between all distributions.
Distribution initialization
Once started, the init process performs various initialization tasks such as:
- Mounting
/proc,/sysand/dev - Configuring cgroups
- Registering the binfmt interpreter (see interop)
- Parsing /etc/wsl.conf
- Starting systemd (see systemd)
- Mounting
drvfsdrives (See drvfs) - Configuring
wslg(see wslg)
Running the distribution
Once ready, init establishes either an lxbus (WSL1) or an hvsocket (WSL2) connection to wslservice. This channel is used to transmit various commands to init (see src/shared/inc/lxinitshared.h), such as:
LxInitMessageInitialize: Configure the distributionLxInitMessageCreateSession: Create a new session leader. See session leaderLxInitMessageTerminateInstance: Terminate the distribution
File: doc/docs/technical-documentation/interop.md
Running Windows executables from Linux
The ability to launch Windows processes from Linux is controlled by 2 different levels of settings:
- The
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LxssManager\DistributionFlagsregistry value, which controls the settings for all Windows users (setting the lowest significance bit disables interop) - The
[interop]section in /etc/wsl.conf, which controls the setting for a given WSL distribution.
binfmt interpreters for Windows executables
To allow Windows process creation from Linux, WSL registers a binfmt interpreter, which tells the kernel to execute an arbitrary command when a specific type of executable is launched via exec*() system calls.
To perform the registration, WSL writes to /proc/sys/fs/binfmt_misc and creates a WSLInterop entry, which points to /init. For WSL1 registration, the entry is written by init for each distribution, for WSL2 mini_init registers the binfmt interpreter at the virtual machine level.
Note: The /init executable is the entrypoint for different WSL processes (init, plan9, localhost, etc). This executable looks at argv[0] to determine which logic to run. In the case of interop, /init will run the Windows process creation logic if its argv[0] value doesn't match any of the known entrypoints.
See: WslEntryPoint() in src/linux/init.cpp.
Connecting to interop servers
When the user tries to execute a Windows process, the kernel will launch /init with the Windows process's command line as arguments.
To start a new Windows process /init needs to connect to an interop server. Interop servers are special Linux processes that act as bridges between Linux and Windows. They maintain secure communication channels (through hvsocket connections) with Windows processes (wsl.exe or wslhost.exe) to launch Windows executables.
Inside Linux, each session leader, and each instance of init has an associated interop server, which is serving via an unix socket under /run/WSL.
/init uses the $WSL_INTEROP environment variable to know which server to connect to. If the variable is not set, /init will try to connect to /run/WSL/${pid}_interop, with its own PID. If that doesn't work, /init will try its parent's pid, and then will continue to go up the chain until it reached init.
Once connected /init sends a LxInitMessageCreateProcess (WSL1) or a LxInitMessageCreateProcessUtilityVm (WSL2), which then forwards that message to the associated Windows process, which will launch the requested command and relay its output to /init.
See src/linux/init/binfmt.cpp
File: doc/docs/technical-documentation/localhost.md
Localhost
localhost is a WSL2 Linux process, created by mini_init. Its role is to forward network traffic between the WSL2 virtual machine, and Windows.
NAT networking
When wsl2.networkingMode is set to NAT, localhost will watch for bound TCP ports, and relay the network traffic to Windows via wslrelay.exe
Mirrored networking
In mirrored mode, localhost registers a BPF program to intercept calls to bind(), and forward the calls to Windows via wslservice.exe so Windows can route the network traffic directly to the WSL2 virtual machine.
Consomme networking
When wsl2.networkingMode is set to Consomme, the VM is given a virtio-net adapter whose host side is backed by Consomme, the user-mode NAT from the OpenVMM project. The guest sees a normal network (a DHCP-assigned address, a default gateway, and working DNS), but rather than going through a host NAT or bridge, its raw Ethernet frames are parsed by a user-mode process on the host and translated into ordinary host sockets. Because all traffic flows through standard host sockets, host networking policies (firewall, VPN routing, proxy settings) apply just as they would for any other host application.
Bound guest ports are tracked and forwarded to the host, optionally via wslrelay.exe.
See src/windows/common/ConsommeNetworking.cpp.
See src/linux/init/localhost.cpp.
File: doc/docs/technical-documentation/mini_init.md
mini_init
mini_init is the first executable that's launched when the WSL2 virtual machine starts. See WSL2 boot process for more details.
Virtual machine setup
mini_init is started when the kernel is done booting, and calls /init, which is mini_init. Like other standard linux init executables, mini_init starts by mounting /proc, /sys, /dev and other standard mountpoints.
mini_init then performs various configuration such as enabling crash dump collection, configuring logging via /dev/console and tty configuration.
Once everything is ready, mini_init connects two hvsockets to wslservice.
One of them, called the "mini_init" channel is used for messages sent by wslservice.exe. See src/shared/inc/lxinitshared.h for a list of messages and responses. Common messages are:
LxMiniInitMessageLaunchInit: Mount a virtual disk and start a new distribution. Seeinitfor more detailsLxMiniInitMessageMount: Mount a disk in/mnt/wsl(used for wsl --mount)EJECT_VHD_MESSAGE: Eject a diskLxMiniInitMessageImport: Import a distributionLxMiniInitMessageExport: Export a distribution
The other hvsocket channel is used to send notifications to wslservice.exe. This is used mainly to report when linux processes exit (which wslservice uses to know when distributions are terminated).
Networking configuration
As part of the boot process, mini_init also launches the gns binary which manages networking configuration
Other tasks
mini_init performs various other maintenance tasks such as:
- Reclaiming unused memory
- Launching the debug shell tty
- Synchronizing IO when the virtual machine terminates
- Resizing filesystem (for wsl --manage
--resize) - Formatting disks (used when installing new distributions)
File: doc/docs/technical-documentation/plan9.md
Plan 9
Plan9 is a Linux process that hosts a plan9 filesystem server for WSL1 and WSL2 distributions. It's created by init in each distribution.
WSL 1
In WSL1 distributions, plan9 serves its filesystem through a unix socket, which can then be connected to from Windows.
WSL2
In WSL2 distributions, plan9 runs its filesystem through an hvsocket
Accessing the distribution files from Windows
From Windows, a special redirector driver (p9rdr.sys) registers both \\wsl$ and \\wsl.localhost. When either of those paths are accessed, p9rdr.sys calls wslservice.exe to list the available distributions for a given Windows user.
When a distribution path is accessed (like \\wsl.localhost\debian), p9rdr.sys calls into wslservice.exe via COM to start the distribution, and connect to its plan9 server, which allows the files to be accessed from Windows.
See src/linux/init/plan9.cpp
2. Official Technical Reference & Guides (microsoft/microsoft.github.io)
[microsoft.github.io](https://microsoft.github.io)
Many open source projects released by Microsoft products, services and teams also have
deployments powered by GitHub Pages on this domain.
To discover Microsoft-released open source projects, learn about Microsoft's open source
approach and other information, check us out online at opensource.microsoft.com.
If we can help answer questions about the open source program at Microsoft, you can
contact opensource at microsoft com - although we are not able to provide support
for projects through this mechanism.
Microsoft GitHub resources
- Default repo templates including
SECURITY.MDand code of conduct files: microsoft/repo-templates - Code of Conduct (FAQ)
Microsoft open source resources
Resources for Microsoft employees
How to identify an official Microsoft organization on GitHub
- Official Microsoft GitHub orgs have a professional avatar and include a web address at Microsoft.com or an associated official domain
- Official Microsoft orgs are Verified on GitHub - look for the domain verification indicator on GitHub