WSL was introduced in 2016. It promises to run unmodifiedLinux binaries in Windows 10. (And with Build 14951, it is also possible to run Windows executables from a WSL distribution).
Microsoft claims, using WSL rather than a «real» virtual machine requires fewer system resources.
WSL versions
As of this writing, there are two WSL versions: WSL 1 and WSL 2.
WSL 1 basically emulates a Linux Kernel while WSL 2 provides a real Kernel running in a lightweight virtual machine.
Thus, WSL 2 has the following three features that are not present in WSL 1:
WSLg is the abbreviation for Windows Subsystem for Linux GUI. This component enables GUI applications in WSL. The fundament of WSLg is the Weston compositor.
Audio (in and out) is supported by a PulseAudio server.
WSLGd
WSLGd is the first process launched after init. This process is similar to a daemon and
starts Weston (with XWayland) and PulseAudio and
then launches mstsc.exe on the host in silent mode in order to establish an RDP connection.
There seems to be no visible process or an executable (binary) with this name.
System Distro
The WSLg System Distro is a containerized Linux environment based on CBL-Mariner where the following components are running.
WSL must be specifically enabled before it can be started. It's possible to enable WSL from the command line with elevated privileges. In order for the enabling to take effect, the computer needs to be restarted.
After the Subsystem for Linux is installed, a distribution needs to be chosen:
C:\Users\Rene> bash
Windows Subsystem for Linux has no installed distributions.
Distributions can be installed by visiting the Microsoft Store:
https://aka.ms/wslstore
Finding distributions
Distributions that are available from the online store can be listed like so:
C:\> wsl --list --online
The following is a list of valid distributions that can be installed.
The default distribution is denoted by '*'.
Install using 'wsl --install -d <Distro>'.
NAME FRIENDLY NAME
* Ubuntu Ubuntu
Debian Debian GNU/Linux
kali-linux Kali Linux Rolling
Ubuntu-18.04 Ubuntu 18.04 LTS
Ubuntu-20.04 Ubuntu 20.04 LTS
Ubuntu-22.04 Ubuntu 22.04 LTS
OracleLinux_8_5 Oracle Linux 8.5
OracleLinux_7_9 Oracle Linux 7.9
SUSE-Linux-Enterprise-Server-15-SP4 SUSE Linux Enterprise Server 15 SP4
openSUSE-Leap-15.4 openSUSE Leap 15.4
openSUSE-Tumbleweed openSUSE Tumbleweed
A list of downloadable (.appx) distributions is here.
WslRegisterDistribution failed with error: 0x800701bc
2023-05-18 on a new laptop, when trying to install Debian, I received the error 0x800701bc along with a link to https://aka.ms./wsl2kernel where I could find more information.
WslRegisterDistribution failed with error: 0x80370102
Still on the 2023-05-18 on a new laptop after updating the kernel, I got the 0x800701bc error along with a link to https://aka.ms./enablevirtualization.
This link suggested to enable hypervisor launch in the boot configuration with bcdedit.exe:
Unfortunately, even after executing add-appxPackage …, there is no distribution installed:
C:\Users\Rene> wsl
Windows Subsystem for Linux has no installed distributions.
Distributions can be installed by visiting the Microsoft Store:
https://aka.ms/wslstore
Update 2025-01-07: Should I have double-clicked the appx file after executing add-appxPackage?
In order to be able to use WSL 2, the Virtual Machine Platformoptional feature must be enabled:
C:\users\rene> wsl --set-default-version 2
Please enable the Virtual Machine Platform Windows feature and ensure virtualization is enabled in the BIOS
For information please visit https://aka.ms/wsl2-install
The Virtual Machine Platform can be enabled like so (with elevated privileges):
C:\users\rene> wsl --set-default-version 2
Error: 0x1bc
For information on key differences with WSL 2 please visit https://aka.ms/wsl2
This thread seems to contain some information on how to get around this issue. It is suggested that the kernel needs to be installed into C:\Windows\System32\lxss\tools.
With DrvFS, a Windows drive is (typically) mounted to /mnt/<drive> (the root of the default mount path can be changed with the root setting under [automount] in /etc/wsl.conf):
A newly plugged in external harddisk can be mounted within WSL like so. The following example assumes that the mounted files need to be accessible by the user whose id is 1000 and corresponding group id is also 1000:
In WSL 2, I've found the 9P fileystem type to access the windows files:
$ sudomount | grep '/mnt/. ' | sed 's/(.*//'
C:\ on /mnt/c type 9p
D:\ on /mnt/d type 9p
E:\ on /mnt/e type 9p
Accessing WSL Filesystem from Windows
In the explorer, the installed WSL filesystem can be accessed via \\wsl$\… or \\wsl.localhost\….
It's thus possible to map a network drive to a running WSL instance:
C:\> net use L: \\wsl$\Debian
The command completed successfully.
C:\> L:
L:\> dir
…
2020-09-03 01:56 AM <DIR> bin
2020-07-10 11:04 PM <DIR> boot
2022-06-01 12:41 AM <DIR> dev
2022-06-01 12:30 AM <DIR> etc
…
L:\> cd etc
L:\> notepadwsl.conf
This mapping is possible because the WSL client runs a 9P protocol file server for which the Windows host s a client (See for example the output of dmesg | grep 9p).
The communication between WSL and Windows runs over AF_UNIX sockets.
Networking
Starting from Windows 11 22H2 and WSL 2.0.9 or later, Windows firewall rules will by default apply to WSL (but see also configuring Hyper-V firewalls).
TCP/IP connections between the WSL guest and the host
From the host or network to the guest
The IP address(es) of the WSL guest can be obtained from within WSL in a shell like so:
A firewall rule, again called usbipd, to allow all local subnets to connect to the service. This firewall rule can be modified to fine tune access control. (If using a third-party firewall, you may have to reconfigure it to allow incoming connections on TCP port 3240.)
usbipd-win can be installed with the following command line (which requires elevated privileges at one point)
C:\> usbipd list
BUSID VID:PID DEVICE STATE
1-3 abcd:1234 USB-Massenspeichergerät Not attached
1-8 04f2:b67c Integrated Camera, Integrated IR Camera Not attached
Binding a USB-ID shares the USB device:
C:\> usbipd bind --busid=1-3
It can now be attached to WSL;
C:\> usbipd attach --wsl --busid=1-3
usbipd: info: Using WSL distribution 'Debian' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Using IP address 172.31.16.1 to reach the host.
Note: usbipd attach requires elevated privileges.
An attached USB device can be detached with usbipd detach ….
Again in WSL
Now, in WSL:
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID abcd:1234 LogiLink UDisk flash drive <<<< this one was added
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
The inserted USB device can finally be mounted:
$ sudo mkdir /mnt/usb
$ sudo mount /dev/sdd1 /mnt/usb
$ ls /mnt/usb
…
TODO
Uh oh:
$ sudo mount /dev/sdf1 /mnt/f
mount: /mnt/f: unknown filesystem type 'ntfs'.
$ cat /proc/filesystems
Interoperability
Interoperability allows to execute Windows and Linux binaries from both, a Windows command terminal or a Linux shell.
The copied .config file enables (quite possibly among others) the config symbolHYPERV:
$ grep CONFIG_HYPERV= .config
CONFIG_HYPERV=y
When I tried to build the Kernel (version WSL 5.15) with the copied .config file, I encountered the error message: FAILED: load BTF from vmlinux: No such file or directory.
I could solve this by commenting the config option CONFIG_DEBUG_INFO_BTF in the .config file.
Update 2023-12-15 (WSL 5.15.133): This step did not seem to be necessary anymore.
Playing Youtube movies in Chrome resulted in choppy audio on a ThinkPad notebook.
This comment suggested to set the config symbolCONFIG_HZ_1000 to y and then recompile the Kernel to solve the issue:
A few times after installing Debian, I found fonts to be crappy (especially in the URL bar) - but I have also had some problems with monospace fonts in both Chrome and gvim.
I was somehow able to mitigate the problems by installing fonts-noto:
$ sudo apt install -y fonts-noto
Installing fontos-noto improved fonts in Chrome's URL bar, but Monospace in was unreadable and Chrome.
I could solve the monospace font problem in Chrome by going to chrome://settings/fonts and then scrolling down to Fixed-width font and replacing Monospace with Liberation Mono.
No sound
A few times, I had no sound. Installing pavucontrol fixed this, too:
$ sudo apt install -y pavucontrol
Failed to configure network (networkingMode Nat). To disable networking, set `wsl2.networkingMode=None` in C:\Users\Rene\.wslconfig
After updating Windows, I couldn't start WSL anymore, the error message being:
Failed to configure network (networkingMode Nat). To disable networking, set `wsl2.networkingMode=None` in C:\Users\Rene\.wslconfig
Error code: Wsl/Service/CreateInstance/CreateVm/ConfigureNetworking/HNS/0x80070424
[process exited with code 4294967295 (0xffffffff)]
You can now close this terminal with Ctrl+D, or press Enter to restart.
Failed to configure network (networkingMode Nat). To disable networking, set `wsl2.networkingMode=None` in C:\Users\Rene\.wslconfig
Error code: Wsl/Service/CreateInstance/CreateVm/ConfigureNetworking/HNS/0x80070424
[process exited with code 4294967295 (0xffffffff)]
You can now close this terminal with Ctrl+D, or press Enter to restart.
I was able to start WSL again by going to Start menu, searching for Turn Windows features on or off and then enabling Virtual Machine Platform (also referred to as VPM).
In a WSL 2 Debian installation, I had sound in Chrome, but when trying use a Csound frontend (blue, csoundqt), these were mute. csoundqt issued this error message PortAudio V19.6.0-devel, … error: No sound device is available … closing device and Failed to initialize real time audio output.
After installing the following package and restarting the WSL distro, I had sound for both, Chrome and csound frontends:
When WSL is instantiated, the Windows host assigns compatible host GPU adapters to the container.
The corresponding virtual GPU devices appear on the PCI bus in the container. These devices are enumerated and accessed by this driver.
Communications with the driver are done by using the Microsoft libdxcore library, which translates the D3DKMT interface to the driver IOCTLs (apparently exposed via /dev/dxg). The virtual GPU devices are paravirtualized, which means that access to the hardware is done in the host. The driver communicates with the host using Hyper-V VM bus communication channels.
This provider is implemented by lxss.sys and lxcore.sys: they coordinate such syscall requests with the Windows NT Kernel.
When the NT Kernel is called with a syscall, the kernel checks if the call came from a pico process by checking the state in the process structure (I assume that to be a special flag).
If this is the case, the kernel saves the register state and «forwards» the call to the pico driver. The pico driver then finds the Linux syscall number in the RAX register and acts accordingly.
After having serviced the request, the calling flow is returned to the NT kernel which restores the register state and puts the return value into the RAX register.
Finally, the execution is returned to the WSL process.
A syscall is forwarded to lxcore.sys (or lxss.sys?) which either (preferrably) dispatches it to an NT syscall or handles it itself.
An example of a nice mapping between a Linux and NT syscall is sched_yield() and ZwYieldExecution().
On the other hand, fork() has no direct equivlent on NT. Therfore, when lxcore.sys (or lxss.sys?) handles a fork() call, it prepares the copying of the process, then calls the NT syscall to create a process and finally finishes the copying.
Cannot be used for interoperability. Provides most features of Linux VFS: permissions, sym-links, FIFOs, sockets and device files. VolFS is used to mount the root file system to /.
DriveFS
Used for interoperability. File names are required to be valid Windows file names and are case insensitive. Windows drives (C:\ etc.) are mounted to /mnt/c etc.).
LxBus provides a channel, based on sockets, on which NT and WSL processes can communicate by exchanging messages and sharing state.
This channel is primarily used by the LXSS Manager service (NT) and /init (WSL).
LxBus is accessed (from the WSL) side by opending the /dev/lxss device (which is not shown with ls /dev/lxss). /dev/lxssclient supports a subset of /dev/lxss.
Update 2024-01-09: On the current environment, this diff command now reports a difference.
This reddit thread has the following interesting comment:
The '/init' executable in WSL2 distros is inserted at runtime by WSL2. It is not shipped by each distro. This executable has multiple functions and will appear several times in the process list while you are running the distro. … there are at least these responsibilities: • run as pid1 to bootstrap the distro when starting it up including setting up wsl specific features, • Marshall interop calls between wsl and windows, • act as a plan 9 file server to share your windows file system with windows, • act as an entry point for binfmt_misc to execute windows binaries via interop.