Windows Subsystem for Linux - explained by a Linux user
Tags: linux, windows, wsl
Published: 2019-10-04 20:59:27

---
title: Windows Subsystem for Linux - explained by a Linux user
published: true
cover_image: https://ricostacruz.com/dev-posts/wsl-explained/cover-image.png?t=1
description:
tags: [Linux, Windows, WSL]
---

You can now run Linux apps on Windows thanks to a feature called [Windows Subsystem for Linux][wsl-faq] ("WSL" for short). But what is it, exactly? Is it an emulation layer like Wine? Is it a VM like VirtualBox? Is it dual-booting like Boot Camp? It's none of the above&mdash;it's something pretty unique and hard to explain.

👇

**Next:** Let me try to explain it anyway!

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Ubuntu as a Windows app

</center>

To get Linux working on Windows, you first need to install Linux. Not from an ISO... but from the Microsoft Store (think: Windows's version of the Mac App Store). A full guide to [installing WSL][wsl-install] is available from Microsoft.

Linux distributions are available as apps. To be specific, they're command-line apps, just like `git` or `vim`.

<figure>
<img src='https://ricostacruz.com/dev-posts/wsl-explained/get-ubuntu.png'>
<figcaption>
<p align='center'>
Many devs use Ubuntu as their Linux distribution in WSL.
</p>
</figcaption>
</figure>

<center>👇</center>

**Next:** To understand WSL, let's first look at how the Windows command line works.

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Command-line apps

</center>

Windows has support command line interface (CLI) apps, just like Linux. In fact, many built-in system utilities are CLI apps.

💡 **Try this:** press `Win` + `R`, then run `ping 8.8.8.8`. It will open a new window.

<figure>
<img src='https://ricostacruz.com/dev-posts/wsl-explained/run-ping.png'>
<figcaption>
<p align='center'>
<em>ping.exe</em> is a built-in command line application.
</p>
</figcaption>
</figure>

👇 **Next:** Let's see what makes this window work.

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Windows console host

</center>

CLI apps are ran inside the [_Windows console host_][conhost]. The console host, or _conhost.exe_, is a GUI app that draws a terminal inteface in a graphical window.

💡**Try this:** open the task manager (`Ctrl` + `Shift` + `Esc`). Now run `ping -t 8.8.8.8`. You'll see a new application in the task manager called _TCP/IP Ping Command_. Under this group are 2 processes:

- _ping.exe_&mdash;the command you just ran; and
- _conhost.exe_&mdash;also known as _Console Window Host_, the GUI that shows ping's output.

<figure>
<img src='https://ricostacruz.com/dev-posts/wsl-explained/ping-task-manager.png' alt='Windows Task Manager showing two processes: conhost.exe and ping.exe'>
<figcaption>
<p align='center'>
<em>ping.exe</em> is running alongside the <em>conhost.exe</em> GUI.
</p>
</figcaption>
</figure>

**In Linux terms:** Think of *conhost.exe* as a terminal emulator, like [XTerm](https://en.m.wikipedia.org/wiki/Xterm) might be for Linux. It's a graphical UI that shows terminal output. *ping.exe* runs on *conhost.exe* in the same way */usr/bin/ping* runs inside *Xterm*.

👇 **Next:** Let's see how the Windows Command Prompt works.

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Cmd.exe on Conhost

</center>

All CLI apps open in _conhost.exe_. This includes the Windows Command Prompt, or *cmd.exe*&mdash;which is a CLI app, just like *ping.exe*!

💡 **Try this:** Go to `Win` + `R` and run `cmd.exe`. You'll see this open in the same Windows _console host_ window that `ping.exe` opened.

<figure>
<img src='https://ricostacruz.com/dev-posts/wsl-explained/run-cmd.png'>
<figcaption>
<p align='center'>
cmd.exe opens in a <em>Conhost</em> window.
</p>
</figcaption>
</figure>

**In Linux terms:** Think of *cmd.exe* like the Bash shell. A terminal window in Linux will run Bash, and will close the window when Bash exits. *cmd.exe* (the shell) and *conhost.exe* (the terminal GUI) works the same way.

<center>👇</center>

**Next:** This may be the case for the Command Prompt, but why does Powershell's window look different?

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Powershell's blue window

</center>

If you open Powershell, you'll notice that the window is blue. It's not a different app, it's still the same _conhost.exe_ with different settings! You'll notice it has the same menus as _cmd.exe_.

`Powershell.exe` is a CLI app, too&mdash;just like `cmd.exe`. _Conhost_ simply lets you choose different settings per app. It simply comes with different color settings for Powershell by default.

<figure>
<img src='https://ricostacruz.com/dev-posts/wsl-explained/cmd-and-powershell.png'>
<figcaption>
<p align='center'>
Powershell's <em>Properties</em> window lets you configure <em>conhost</em> settings.
</p>
</figcaption>
</figure>

**In Linux terms:** Most terminal emulators on Linux would support different profiles, and you may be assigning different profiles per command. Windows's _conhost.exe_ has a different profile for Powershell that has its *Screen Background* set to blue.

<center>👇</center>

**Next:** Is WSL just like _cmd.exe_ and Powershell then?

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## The WSL launcher: `wsl.exe`

</center>

Yes! You can think of WSL as another CLI application just like _cmd.exe_ and _powershell.exe_. Just like other CLI apps, you can run `wsl.exe`. This is the _WSL Launcher_, which boots up the WSL platform and drops you into the bash (your user's shell by default).

💡 **Try this:** Try running `wsl.exe` via `Win` + `R`. This should get you a Linux bash prompt running inside a _conhost.exe_ window. Seems very similar to Cmd and Powershell, doesn't it?

<figure>
<img src='https://ricostacruz.com/dev-posts/wsl-explained/run-wsl.png'>
<figcaption>
<p align='center'>
Running <code>wsl</code> gets you a <em>conhost</em> window, just like <em>cmd.exe</em>.
</p>
</figcaption>
</figure>

<center>👇</center>

**Next:** Let's try mixing all these together.

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Shells inside shells

</center>

Windows's *cmd.exe* and *powershell.exe* can run command line applications. You can use it to run `ping.exe`, `chkdsk.exe`, or&mdash;wouldn't you know it&mdash;even `wsl.exe`.

💡 **Try this:** Try running `wsl.exe` or `bash.exe` from within a Command Prompt (*cmd.exe*). In fact, try running `wsl.exe` inside `powershell.exe` inside `cmd.exe`, or any combination above! Typing `exit` will bring you one level out.

<img src='https://ricostacruz.com/dev-posts/wsl-explained/nested-shells.png'>

**In Linux terms:** Think of them just like shells. Windows's *Cmd* might be like Bash, and *Powershell* might be [Fish] or [Zsh]. `wsl.exe` works the same way.

<center>👇</center>

**Next:** Why do the backslashes (`\`) in Windows appear as forward slashes (`/`) in WSL?

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## The WSL filesystem

</center>

WSL has its own filesystem! If you do `ls /` inside WSL, you'll find `/usr`, `/bin` and the other usual suspects in a Linux filesystem. This is a full POSIX-compliant filesystem managed by WSL, away from the limitations of your Windows's NTFS.

💡 **Try this:** Go to your Linux's home directory with `cd`. Create two files with the same filename, but different case: `touch xyz.txt XYZ.TXT`. These two files can't co-exist in Windows's case-insensitive filesystem, can it? They will live happily inside WSL just fine.

<img src='https://ricostacruz.com/dev-posts/wsl-explained/case-sensitive-files.png'>

**In Linux terms:** Think of WSL as a separate Linux system&mdash;a bit like a VirtualBox VM. It has its own filesystem, processes, `/dev` devices. Running `wsl.exe` will tunnel you into this Linux subsystem.

<center>👇</center>

**Next:** So is it a virtual machine?

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Linux in a box

</center>

Not only does WSL have its own filesystem, it's a full Linux system that runs as an app in Windows! It may be easy to think it's like VirtualBox, but it's not a VM.

**Why is it not a VM?** There's no CPU or hardware emulation involved like in a VM. A whole Linux system runs like any other app in Windows.

💡 **Try this:**  Run `htop` inside WSL (you may need to install it first), and view it as a tree (`shift-T`). It has a whole process tree, even with an `/init` process! You'll see your machine's full CPU and memory capacity&mdash;it's not pre-allocated, unlike a VM. It shares these hardware resources just as any other Windows app would.

<img src='https://ricostacruz.com/dev-posts/wsl-explained/htop.png'>

**In Linux terms:** On a typical system, Linux's entry point would be in */boot/vmlinuz-linux*, which is fired by a bootloader like GRUB. Think of WSL as a version of this packaged as a *wsl.exe* file. The whole Linux subsystem will be running as a process inside Windows.

**Note about WSL2:** There are two versions of WSL. The new experimental version, [WSL2](https://docs.microsoft.com/en-us/windows/wsl/wsl2-install), actually works as a Virtual Machine.

<center>👇</center>

**Next:** If WSL is a separate subsystem from your Windows environment, how do they share files?

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Windows files inside WSL

</center>

Your Windows files are visible inside WSL under `/mnt/c`.

💡 **Try these:** Here are some experiments you can try inside WSL:

- **Case insensitive files:** In WSL, try `cd /mnt/c/Windows` and `cd /mnt/c/WINDOWS`. They'll both work! The Windows filesystem you're accessing in `/mnt/c` is case-insensitive.

- **Check mount points:** Run `findmnt`. You'll see `/mnt/c` is mounted as *drvfs*, just as how you would mount a drive in Linux.

- **Two home directories:** Look at `/mnt/c/Users`. You'll see you have 2 home directories: your WSL/Linux one in `/home`, and your Windows one in `/mnt/c/Users`.

- **Permissions won't work:** Try to make a file in `/mnt/c` and run `chmod` to change its permissions. It won't work&mdash;the filesystem these files live on is NTFS, which doesn't support UNIX-style permissions.

<figure>
<img src='https://ricostacruz.com/dev-posts/wsl-explained/findmnt.png'>
<figcaption>
<p align='center'><em>findmnt</em> will tell you where <code>/mnt/c</code> comes from.</p>
</figcaption>
</figure>

<center>👇</center>

**Next:** We can see Windows files in WSL. Can we see WSL files in Windows?

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## WSL files from Windows

</center>

WSL exposes your files as a network resource in `\\wsl$`. (The actual files live [somewhere](https://superuser.com/a/1280916) in `C:\Windows`, though it's not a good idea to use them directly.)

💡 **Try this:** Open Windows Explorer. In the location bar, type in `\\wsl$\Ubuntu`. This should get you access to the WSL filesystem as a network folder.

<img src='https://ricostacruz.com/dev-posts/wsl-explained/explore-ubuntu.png'>

**In Linux terms:**  `\\wsl$\Ubuntu` is called a UNC path, which is Windows's way of accessing network resources. Think of it like `smb://wsl/Ubuntu`.

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Running Windows apps in WSL

</center>

You can run Windows `*.exe` programs inside WSL. It will simply open them in Windows, just as you would have ran those programs from Windows itself.

💡 **Try this:** In WSL, type `notepad.exe`. In fact, you can even try running `cmd.exe`&mdash;this should get you a Windows command prompt! To see how this works, try `which notepad.exe`, which shows that it's simply running `/mnt/c/WINDOWS/system32/notepad.exe`.

```
user@desktop ~$ notepad.exe
```

**In Linux terms:** Linux can run ELF binaries (ie, Linux's native executable format). Once it finds a PE32+ binary (ie, Windows's format), it'll simply tell Windows to open it outside of WSL. Also, Windows's `%PATH%` carries over into Bash's `$PATH`, making the system `.exe` files available anywhere in WSL.

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Running WSL apps in Windows

</center>

Linux apps can be ran from Windows using `wsl.exe`, the WSL launcher. This starts up the WSL subsystem (if it hasn't been yet) and runs a command from within it.

**Try this:** Open a command prompt (`Win`+`R` to run `cmd.exe`), then type: `wsl ls /`

```
Microsoft Windows [Version 10.0.18985.1]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\>wsl ls /
bin/   dev/  home/  lib/    lost+found/  mnt/  proc/  run/
boot/  etc/  init*  lib64/  media/       opt/  root/  sbin/
...
```

---

<center>👇</center>

**Next:** Can we replace conhost?

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Alternatives to _conhost_

</center>

You don't need to use _conhost.exe_ to run CLI apps. You can run them in third party terminal emulators. There's [wsltty](wsltty) (based on Cygwin's mintty), [Terminus](terminus) (an Electron-basde terminal), [Conemu](conemu) (supports tabs and panes), and a few more.

Any of these apps can run any CLI application. They often usually come with built-in shortcuts for cmd, Powershell, WSL, and possibly a few others.

**In Linux terms:** Just like XTerm has many alternatives, conhost has its own alternatives as well.

[conemu]: https://conemu.github.io/
[wsltty]: https://github.com/mintty/wsltty
[windows-terminal]: https://github.com/microsoft/terminal
[terminus]: https://eugeny.github.io/terminus/

<figure>
<img src='https://ricostacruz.com/dev-posts/wsl-explained/windows-terminal.png'>
<figcaption>
<p align='center'>
Windows Terminal is an alternative to conhost. It supports WSL, Powershell, cmd, and more.
</p>
</figcaption>
</figure>

<center>👇</center>

**Next:** Let's recap what we know so far.

---

<center>

<br><img src='https://ricostacruz.com/dev-posts/wsl-explained/icon.png' width='80'><br>

## Recap

</center>

- **Ubuntu is a command-line app.** It's installed from the Microsoft Store.

- **Windows provides `wsl.exe` that launches an installed Linux distribution** (Ubuntu in this case). This is a command-line program that brings you to a Bash prompt. There's also `bash.exe`, which does the same thing (it's like an alias for *"wsl.exe bash"*).

- **CLI apps:** are ran inside `conhost.exe`, the built-in Windows terminal. There are alternatives to this that developers might like better.

- **Environments:** `cmd.exe`, `powershell.exe`, and `wsl.exe`

- **WSL launcher:** `wsl.exe` runs the WSL subsystem and drops you into a Bash prompt. It's just a CLI app.

[conhost]: https://docs.microsoft.com/en-us/previous-versions/orphan-topics/ws.11/mt427362(v=ws.11)?redirectedfrom=MSDN
[fish]: https://fishshell.com
[zsh]: https://en.wikipedia.org/wiki/Z_shell
[wsl-install]: https://docs.microsoft.com/en-us/windows/wsl/install-win10
[wsl-faq]: https://docs.microsoft.com/en-us/windows/wsl/faq