Level 0 · Chapter 6
WSL: a second environment subsystem
How Windows runs real Linux binaries — the modern answer to the old POSIX subsystem box in the architecture diagram.
The classic Windows architecture diagram draws "environment subsystems" as a set of alternatives sitting side by side on top of the same Executive: Win32, POSIX, OS/2. GUI & windowing and the rest of this level have been about the Win32 one — the one that won, and the one everything else in this course assumes. POSIX and OS/2 support were removed from Windows decades ago. But the idea — "a second, non-Win32 way to run programs on the same kernel" — didn't die with them. WSL (Windows Subsystem for Linux) is its direct, actively developed successor, and it's worth understanding precisely because it took two genuinely different architectural approaches across its two major versions.
WSL1: a real environment subsystem, in the original sense
WSL1's design is the closer match to what the old diagram meant by "environment subsystem." It doesn't run a Linux kernel at all — it runs unmodified Linux binaries directly on the NT kernel, by translating what they ask for:
- Pico processes are the foundation: an NT process stripped down to almost nothing Windows-specific — no PEB in the usual sense, no ordinary Win32 environment block — just enough structure for the NT Process Manager (covered in Processes & threads) to schedule and manage it.
- A kernel-mode driver, historically called lxss (later lxcore), intercepts the Linux system calls that pico process makes and translates each one onto real NT kernel operations: a Linux
open()becomes an NT file operation through the ordinary I/O Manager path; a Linuxfork()gets mapped onto NT process-creation primitives, even though the two models don't line up perfectly.
This is genuinely the same spirit as the old POSIX subsystem: take a foreign API surface and make it work by translating it onto NT's actual primitives, without running a second kernel. The catch is exactly what you'd expect from a translation layer: Linux and NT don't agree on everything a syscall-heavy program might rely on, and WSL1 has to approximate or work around genuine semantic gaps (specific filesystem behaviors, certain networking primitives) that don't have a clean one-to-one NT equivalent.
WSL2: not translation — virtualization
WSL2 takes a completely different, arguably more pragmatic approach: instead of translating Linux calls onto NT, it runs a real, Microsoft-maintained Linux kernel, inside a lightweight Hyper-V child partition — exactly the root/child partition model covered in Hyper-V & partitions. From the Linux kernel's point of view, it's running on ordinary (virtual) hardware, handling its own system calls natively, with no translation layer involved at all.
What makes WSL2 not feel like "a VM" in the way people usually mean that: Microsoft built tight integration on top of the same VMBus-based mechanisms Hyper-V & partitions describes — a 9P-based network file-sharing protocol lets Windows and Linux see each other's files without manual configuration, a dedicated network stack gives the Linux guest working connectivity automatically, and process interop lets you invoke a Windows .exe from a Linux shell (and a Linux binary from cmd.exe or PowerShell) almost transparently.
Why the distinction is worth knowing, not just trivia
Because the two versions solve the same user-facing problem ("run Linux software on Windows") through fundamentally different mechanisms, they have different performance and compatibility characteristics that aren't obvious from the outside:
- A workload doing large numbers of small, syscall-heavy operations can behave very differently: WSL1 pays a translation cost per call (and can hit genuine semantic gaps where Linux and NT just don't agree), while WSL2 runs those same calls against a real Linux kernel, but pays a VM-boundary cost for anything that has to cross into the Windows host (file access into the Windows filesystem, for instance).
- WSL1's compatibility ceiling is bounded by how completely NT's primitives can be translated into Linux semantics — there are real workloads (certain low-level networking tools, software expecting exact Linux-specific
/procbehavior) that WSL1 can't fully support. WSL2, running an actual Linux kernel, doesn't have that ceiling in the same way.
A common mistake
Talking about "WSL" as a single, unified thing glosses over what's actually a genuine architectural fork. WSL1 is a translation-based environment subsystem, a real descendant of the same idea the old POSIX subsystem represented. WSL2 is a virtualization story, and understanding its performance and behavior has much more in common with Hyper-V & partitions than with anything else in this level. Treating them as interchangeable "just run Linux stuff" features hides exactly the distinction that explains why the same command can behave differently between the two.
Where this connects
- Virtualization & the hypervisor and Hyper-V & partitions cover the partition model WSL2 is built directly on top of.
- Ntdll & the user/kernel boundary covers the native NT syscall boundary WSL1's translation driver sits underneath, on the Windows side.
- Processes & threads covers the
EPROCESS/ETHREADstructures a WSL1 pico process is a minimal, stripped-down instance of.