WSLを理解する

## はじめに
私はWindowsユーザーで、最近になりWSLというものを使い始めました。今のところ、Windows上でLinux環境が動作する便利なやつだと理解しています。特にVisual Studio CodeをWSL経由で立ち上げると、ディレクトリ構成がLinuxのそれになって「おお、これだ！勉強したやつじゃん！」とちょっと感動しました。なかなか距離の縮まらないLinuxとの仲を取り持ってくれたWSLのことを深く理解してみたいと思います。
特に、パスの謎について。よく目にする`/mnt/c/Users/Username/Documents`の`mnt`。ずっと感じていた「なにこれ？」を紐解きたいと思います。

## WSLとは？
WSLはWindows Subsystem for Linuxの略で、ドキュメントには以下のような説明があります。
> "Linux 用 Windows サブシステム (WSL) を使用すると、開発者は、従来の仮想マシンまたはデュアルブートセットアップのオーバーヘッドなしで、ほとんどのコマンドラインツール、ユーティリティ、アプリケーションなどを含む GNU/Linux 環境を、変更せずに Windows 上で直接実行できます。"
> 出典：https://learn.microsoft.com/ja-jp/windows/wsl/

現在はWSL2が規定となっていますが、WSL2は仮想マシンやデュアルブートで立ち上げるものではないとのこと。これは使っていても実感できるところです。以降、WSL2について調べていきたいと思います。

>"WSL 2 は仮想化テクノロジを使って、軽量のユーティリティ仮想マシン (VM) 内で Linux カーネルを実行します。 Linux ディストリビューションは、WSL 2 のマネージド VM 内の分離されたコンテナーとして実行されます。 WSL 2 から実行された Linux ディストリビューションは、同じネットワーク名前空間、デバイスツリー (/dev/pts 以外)、CPU/カーネル/メモリ/スワップ、/init バイナリを共有しますが、PID 名前空間、マウント名前空間、ユーザー名前空間、Cgroup 名前空間、init プロセスは独自のものを使います。"
>出典：https://learn.microsoft.com/ja-jp/windows/wsl/about

従来の仮想マシンではないけれども、仮想化技術は使用しており、仮想化技術を使ってLinuxカーネル（OSをうまく動かすシステム）を実行しているということですね。
そしてこの仮想マシン内に作られたコンテナでLinuxディストリビューション（ubuntu等）が実行されている様です。
Dockerはホストとカーネルを共有していますが、WSL経由でDockerを立ち上げることでLinuxカーネルを直接使えていると理解しました。
また、ホストと共有している空間と分離されている空間があるということなので、各空間の意味を深ぼっていくとよさそうです。この空間とは、Linuxの名前空間という機能で、各プロセスが互いに干渉しないように安全に動かすための仕組みのことです。

### 1.ホストと共有する空間
- ネットワーク名前空間
→ホストとIPアドレスを共有している。
- デバイスツリー (/dev/pts 以外)
→ホストとハードウェアを共有しているためLinux側からアクセスできる。（DockerもWSL経由のため同様）
- CPU/カーネル/メモリ/スワップ
→ホストとWSLでリソースをうまいこと使っている。
- /init バイナリ
→WSLがLinuxディストリビューションを起動する時、最初に実行されるプロセス。複数のディストリビューションをWSLで使用している場合に便利らしい。

### 2. ホストと共有しない独自の空間
- PID 名前空間
→プロセスIDのこと。ホストと同じPIDでも、ホストとは別のプロセスとして識別される。競合がおきない。
- マウント名前空間
→ホスト（Windows）とLinuxのディレクトリ構造を分離する。
- ユーザー名前空間
→ホストの管理者権限とLinuxのroot権限を区別する。
- Cgroup 名前空間
→Control GroupsというLinuxの機能。CPUやメモリのリソースを制御する。WSL内のプロセスで高負荷がかかる時に、過度にリソースを使ってホストに影響を与えないようにする。
- init プロセス
→ディストリビューションの起動や停止は/initバイナリを共有することで一括で行えるが、各プロセスは分離しているということの様。（これはホストではなくディストリビューション内での分離のような？）

全体を通して、ホストとは同一のハードウェアを共有し、うまいこと協調している。ホスト側のファイルにもアクセスできる。ネットワーク環境も一緒だからインターネットへアクセスできるし、ローカルホストとして自身にアクセスすることもできる。
一方で、ホストとWSL側のプロセスは分離されていて、ディレクトリ構造やユーザーの権限も分離されているといったようなことだと理解しました。
この辺りについては、Linuxの名前空間についての理解を深めていく必要があると感じます。今後の課題です。

## LinuxとWindowsのディレクトリ構成
次にLinuxとWindows間でのファイルの移動方法について理解していきたいと思いますが、その前にこれらのOSのディレクトリ構成について簡単に確認しておきたいと思います。

### 1. Linuxのディレクトリ構成
Linuxは`/(ルートディレクトリ)`を頂点にしてその下にディレクトリが作られています。つまりてっぺんが一つなんですね。
```bash
/ (root)
├── /bin
├── /boot
├── /dev
├── /etc
│   ├── /network
│   ├── /passwd
│   └── ...
├── /home
├── /lib
├── /media
├── /mnt
├── /opt
├── /proc
├── /root
├── /sbin
├── /srv
├── /sys
├── /tmp
├── /usr
├── /var
│   ├── /log
│   ├── /mail
│   └── /spool

```
例えば、ホームディレクトリの中に”test”というディレクトリを作り、その中に”test.py”というファイルを作成した場合、絶対パスは`/home/<ユーザー名>/test/test.py`となります。
恥ずかしい話ですが、自分は最近までホームディレクトリというのが`/home/`のことだと勘違いしていました。そのせいで認識の齟齬に苦しみました。

### 2. Windowsのディレクトリ構成
一方、Windowsにおけるルートディレクトリはドライブごとに存在します。
```makefile
C:\
├── Windows
├── Program Files
├── Program Files (x86)
├── ProgramData
├── Users
│   └── yourname
│       ├── Desktop
│       ├── Documents
│       ├── Downloads
│       └── ...
└── ...

D:\
├── Data
├── Backup
└── ...

E:\
├── Media
└── ...
```

たとえばドキュメントフォルダに`test.py`を作成した場合、絶対パスは
`C:\Users\<ユーザー名>\Documents\test.py`となります。Windowsは`\（バックスラッシュ）`が階層を区切る記号なんですね。こんなところで個性を出すのはやめてほしいです。

WSLからWindowsを見た時、パスの形式は以下のようになります。
```bash
# Windowsパス：  C:\Users\<ユーザー名>\Documents\test.py
# WSLパス：     /mnt/c/Users/<ユーザー名>/Documents/test.py
```
階層を区切る表記が変わるのは理解できますが、急に出てくる'/mnt/'が謎ですよね。次にこれが必要な理由を探っていきたいと思います。

## WindowsとLinux間でのファイルの移動
WSLからWindows側のファイルを移動してくるとき、表記としては以下のようになります。

```bash
# mv <Windowsのファイルのパス> <移動先のフォルダ>
mv /mnt/c/Users/<ユーザー名>/Documents/test.py ~/<移動先のフォルダ>/
```
この`/mnt/`については、公式ドキュメントの[こちら](https://learn.microsoft.com/ja-jp/windows/wsl/filesystems)を見ると解決できそうです。

> "WSL コマンド ラインのファイル パスに /mnt/ が含まれている場合は、マウントされたドライブから作業していることを意味します。 したがって、Windows ファイルシステムの C:/ ドライブ (C:\Users\<user name>\Project) は、マウントされているとき、WSL コマンド ラインで次のようになります: /mnt/c/Users/<user name>/Project$。 マウントされたドライブにプロジェクト ファイルを格納することは可能ですが、\\wsl$ ドライブに直接格納すれば、パフォーマンス速度が向上します。"

`/mnt/`は前述したLinuxのディレクトリ構成のうちの一つですね。`/mnt/`が含まれている場合、ドライブを接続しているということの様です。
mntはマウントという意味のようですね。マウントという言葉は、"接続した機器を認識させて使える状態にする"ということのようです。(https://wa3.i-3-i.info/word13188.html)
つまり、`/mnt/c/Users/<ユーザー名>/Documents/test.py`は`/mnt/`というLinuxのディレクトリに、WindowsのCドライブをマウント（接続）しているということなのですね。
WSLというのは、仮想マシンに立ち上げたLinuxディストリビューションとホストであるWindowsの橋渡しをするインターフェースの役割を担っている様です。


## WSLのインストールされている場所
ここまでで`/mnt/`についての疑問は解決できましたが、WSLがWindowsのどこにインストールされているかについても調べてみたいと思います。上記で参照した[ページ](https://learn.microsoft.com/ja-jp/windows/wsl/filesystems)の中に、"Windowsエクスプローラーで現在のディレクトリを表示する"という項目があります。エクスプローラーのアドレスバーに'\\wsl$'を入力すると、WSLのディレクトリを参照することができます。
ただ、これはネットワーク内にフォルダがあるという表示になっています。どうやらこれはホストとネットワークを共有する仕組みによって可能になっているコマンドのようです（実際はローカルの仮想ファイルシステムにアクセスしていると思うのですが）。WSL内のファイルを参照するためのコマンドで、パスはこちらからは確認できないのですね。
WSLが保存されている場所は以下になります。
```
C:\Users\<ユーザー名>\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_<ランダム文字列>\LocalState\
```
## おわりに
今回の学習でWSLについての理解を深めることができました。ただ、調べるほどに奥が深く、まだまだ掘り下げる部分があるなと感じました。また、Linuxやハードウェアについての理解を深める必要性もありそうです。今後の学習に繋げていきたいと思います。