Skip to main content
LXSS subsystem architecture and lxrun management tool from the original Windows Subsystem for Linux

LXSS and lxrun — Early WSL Internals

The LXSS subsystem and the lxrun command-line tool were the internal machinery behind the first release of the Windows Subsystem for Linux — what is now called WSL 1. Understanding what they were, how they worked, and why Microsoft replaced them matters because a significant volume of WSL troubleshooting content on the web still references LXSS-era behaviour, lxrun commands, and architectural assumptions that no longer hold. This technical note documents the subsystem's architecture, the lxrun command set, the filesystem layout, the transition to WSL 2's lightweight VM model, and the specific points where old guidance now leads people astray. The note draws on direct observation of the subsystem behaviour across Windows 10 Insider builds and release versions. It sits within the tech notes section and connects to the broader Linux on Windows topic hub.


What LXSS actually was

→ Short Answer

LXSS (Linux Subsystem) was a kernel-mode driver and associated user-mode service that translated Linux system calls into NT kernel equivalents in real time. It was not a virtual machine. It did not run a Linux kernel. It intercepted every syscall from a Linux ELF binary, mapped it to the closest NT equivalent, and returned the result in a format the Linux process expected. The subsystem was managed through lxrun.exe on the Windows side and the LXSS Manager service (LxssManager).

The translation layer architecture

When you launched Bash on Ubuntu on Windows (the original branding), the following happened:

  1. bash.exe started on the Windows side, acting as the console host for the Linux environment.
  2. LxssManager service initialised the subsystem, setting up the filesystem namespace, process table, and signal infrastructure.
  3. The lxss.sys kernel driver loaded, registering itself as a handler for Linux ELF binaries and providing the syscall translation layer.
  4. An init process started within the LXSS environment, behaving as PID 1 for the Linux process tree.
  5. Linux processes executed natively — they were real processes visible in Task Manager as bash.exe or wsl.exe children — but every kernel interaction went through the translation layer rather than a Linux kernel.

This architecture had a specific set of strengths and limitations. Syscalls that had clean NT equivalents — file I/O, process management, basic networking — worked well and performed close to native speed. Syscalls that had no NT equivalent — inotify, cgroups, certain ptrace operations, some ioctl calls — were either partially implemented, stubbed out, or returned ENOSYS.

⬡ Observed Behaviour

Applications that depended on inotify for filesystem change notification (including many Node.js development tools, file watchers, and build systems) either did not work at all or fell back to polling mode under LXSS. The translation layer could not replicate inotify semantics on top of the NT notification model with full fidelity. This was one of the most commonly encountered limitations in practice and a frequent source of confusion when tools worked on native Linux but failed silently or performed poorly under WSL 1.

Architecture diagram showing LXSS syscall translation layer between Linux ELF processes and the NT kernel

The lxrun command set

lxrun.exe was the management tool for the LXSS subsystem. It handled installation, removal, and configuration of the Linux environment before Microsoft introduced the wsl.exe command-line tool.

Key commands

Windows Command Prompt
lxrun /install          Install the Linux subsystem (Ubuntu)
lxrun /uninstall Remove the Linux subsystem
lxrun /uninstall /full Remove the subsystem and all user data
lxrun /update Update the Linux subsystem
lxrun /setdefaultuser Set the default Linux user

There was no distribution choice. lxrun /install installed Ubuntu — specifically, the Ubuntu image Microsoft packaged for WSL. The concept of multiple installable distributions came later, after lxrun was already on its way out.

Filesystem layout under lxrun

The LXSS filesystem lived under the Windows user profile directory:

%LOCALAPPDATA%\lxss\
├── rootfs\ ← The Linux root filesystem
├── root\ ← Root user home directory
└── home\ ← User home directories

This was a normal Windows directory on the NTFS volume. The Linux filesystem permissions, ownership, and special file types (symlinks, device nodes, sockets) were stored as NTFS extended attributes — specifically in EA (Extended Attribute) data attached to each file.

⚠ Common Pitfall

Modifying files inside the %LOCALAPPDATA%\lxss\ directory from Windows — using Explorer, Notepad, or any Windows tool — was explicitly unsupported and could corrupt the Linux filesystem. Windows tools did not preserve the NTFS extended attributes that stored Linux permissions and metadata. A file edited from Windows would lose its Linux ownership and permission bits, and in some cases the file would become invisible or inaccessible from the Linux side. This was the single most frequently encountered data loss scenario with WSL 1, and the warning was not prominent enough in early documentation.


What changed when WSL 2 arrived

↻ What Changed

WSL 2, announced in 2019 and generally available in Windows 10 version 2004 (build 19041), replaced the LXSS syscall translation architecture entirely. Instead of translating individual syscalls, WSL 2 runs a real Linux kernel inside a lightweight Hyper-V virtual machine. The kernel is maintained by Microsoft but is a genuine Linux kernel — it handles syscalls natively, supports the full Linux syscall surface, and runs ext4 as its root filesystem inside a virtual hard disk (VHDX file).

The architectural difference is fundamental:

Then

WSL 1 / LXSS: No Linux kernel. Every syscall translated by lxss.sys into NT equivalents. Filesystem on NTFS with metadata in extended attributes. Network stack shared with Windows. No VM overhead, but incomplete syscall coverage. lxrun managed the single Ubuntu environment.

Now

WSL 2: Real Linux kernel in a lightweight VM. Full syscall compatibility. ext4 root filesystem in a VHDX. Virtual network adapter with NAT. VM has startup overhead (typically under 2 seconds) but provides complete Linux kernel functionality including inotify, cgroups, Docker support, and kernel modules. wsl.exe manages multiple distributions.

Performance implications

The performance characteristics reversed between the two architectures in ways that still cause confusion:

Filesystem I/O within the Linux filesystem: WSL 2 is dramatically faster because it uses a native ext4 filesystem on a virtual disk, rather than the NTFS translation layer. Operations like git status on a large repository, npm install, or compilation are typically 2–5x faster under WSL 2 for files stored in the Linux filesystem.

Cross-filesystem I/O (accessing /mnt/c): WSL 1 was faster for accessing Windows files because there was no filesystem boundary to cross — it was all NTFS. Under WSL 2, accessing /mnt/c involves the 9P filesystem protocol over Hyper-V sockets, which introduces latency. Operations on Windows files from inside WSL 2 can be noticeably slower than the same operations under WSL 1.

This trade-off is the reason the standard advice is to keep project files inside the WSL 2 Linux filesystem (/home/user/projects/) rather than on the Windows mount (/mnt/c/Users/.../projects/). The rm -rf in WSL technical note covers the specific behavioural implications of filesystem operations across this boundary.

Comparison of WSL 1 LXSS translation architecture versus WSL 2 lightweight VM with Linux kernel

The deprecation of lxrun

lxrun.exe was deprecated in Windows 10 version 1803 (April 2018 Update) and removed entirely in later builds. Its replacement is wsl.exe, which provides a superset of functionality:

lxrun commandwsl.exe equivalent
lxrun /installwsl --install
lxrun /uninstallwsl --unregister <distro>
lxrun /setdefaultuser<distro> config --default-user <user>
(no equivalent)wsl --list --verbose
(no equivalent)wsl --set-version <distro> 2
(no equivalent)wsl --import / wsl --export

The wsl.exe tool supports multiple distributions (Ubuntu, Debian, Fedora, openSUSE, Alpine, and others from the Microsoft Store), per-distribution WSL version selection, import/export of distribution images, and detailed status reporting. It is a complete management interface where lxrun was a minimal bootstrap tool.

⚙ Compatibility Note

If you encounter scripts, documentation, or registry hacks that reference lxrun, lxss.sys, or the %LOCALAPPDATA%\lxss\ filesystem path, you are looking at WSL 1-era material. These tools and paths do not exist on modern Windows installations. The equivalent modern paths store distribution filesystems as VHDX files under %LOCALAPPDATA%\Packages\ in distribution-specific directories. The registry keys associated with LXSS Manager have also changed significantly between WSL 1 and WSL 2.


Why old LXSS-era guidance causes problems today

A substantial volume of WSL troubleshooting content on forums, Stack Overflow, and blog posts was written during the WSL 1 era and references LXSS-specific concepts:

"Edit files from Windows at %LOCALAPPDATA%\lxss\rootfs\" — This path does not exist under WSL 2, and even under WSL 1 it was a data corruption risk. The WSL 2 filesystem is inside a VHDX that is not directly browsable from Windows in the same way. The correct modern approach is \\wsl$\<distro>\ from Windows Explorer.

"Use lxrun /uninstall /full to reset" — The command does not exist. The equivalent is wsl --unregister <distro> followed by reinstallation from the Store.

"Set DISPLAY=localhost:0 for X11" — This worked under WSL 1 (shared networking) but does not work under WSL 2 (NAT networking) unless mirrored mode is enabled. The X11 on WSL guide covers the correct approaches for each configuration.

"WSL cannot run Docker" — True for WSL 1 (LXSS could not emulate the kernel features Docker requires). False for WSL 2 (Docker Desktop integrates directly with WSL 2's Linux kernel, and Docker Engine runs natively inside WSL 2 distributions).


LXSS in the registry

For those doing forensic or historical work, the LXSS Manager left traces in the Windows registry:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss

Under WSL 2, distribution registrations are stored in a similar location but with different subkey structures. Each distribution has a GUID-identified subkey containing the distribution name, filesystem path (VHDX location), version (1 or 2), and default user ID.

The LxssManager Windows service still exists under WSL 2 — it manages distribution lifecycle — but its internal operation is entirely different. Under LXSS, it managed the syscall translation environment. Under WSL 2, it manages the lightweight VM and distribution VHDX lifecycle.


Practical value of understanding LXSS

Knowing about LXSS and lxrun serves three practical purposes today:

Filtering outdated advice. When troubleshooting WSL issues, recognising LXSS-era terminology lets you immediately identify guidance that does not apply to your WSL 2 environment and skip to relevant solutions.

Understanding performance characteristics. The filesystem performance differences between WSL 1 and WSL 2 — particularly the cross-filesystem penalty — are a direct consequence of the architectural change from LXSS translation to VM-based isolation. Knowing why the architecture changed helps you make informed decisions about file placement and workflow design.

Appreciating the engineering trajectory. The LXSS approach was ambitious — translating an entire operating system's syscall interface in real time — and it worked remarkably well for a first attempt. Its limitations drove the move to WSL 2, but the translation layer proved the concept that serious Linux development could happen on Windows, which justified the investment in the VM-based architecture that followed.