MS_WSLInterop - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki

WSLでのWindowsとLinuxの相互運用

概要

ファイルシステム、環境変数、プログラム実行辺りの話。

詳細

相互運用の有効化・無効化

有効化

$ echo 1 > /proc/sys/fs/binfmt_misc/WSLInterop

無効化

$ echo 0 > /proc/sys/fs/binfmt_misc/WSLInterop

補足(現在は設定ファイルで制御する): binfmt_misc を直接叩く方法は
再起動で元に戻るため、現在は /etc/wsl.conf に書くのが標準である。

[interop]
enabled = false          # Windows の実行ファイルを起動しない
appendWindowsPath = false # Windows の PATH を引き継がない

appendWindowsPath = false は、Windows 側の PATH が長大で
Linux 側のコマンド解決が遅くなる・意図せぬ実行ファイルを拾う
といった問題への対処としてよく使われる。

ファイルシステム

DrvFs

  • WSL 環境に Windows のボリュームをマウントし、
    Linux から Windows のファイルにアクセスできるようにする仕組み。

  • 以下のようなパスで、Windows のボリュームにアクセス出来る。

    $ dir /mnt
    c  d
    $ dir /mnt/c
    ...

P9

WSL2から、DrvFs は、P9 に置き換えられる。

補足(/mnt/c は遅い): WSL2 の 9P はネットワーク ファイル
プロトコルであり、Windows 側のファイルへのアクセスは
WSL1 の DrvFs より大幅に遅い

逆に、Linux 側(ext4 の仮想ディスク)へのアクセスは WSL2 の方が速い。
このため WSL2 では 作業ディレクトリを /home 配下に置き、
/mnt/c 配下でビルドしない
のが定石である
(Windows から Linux 側を見るときは \\wsl$\<distro> を使う)。
なお、Windows 11 の新しいビルドでは 9P に代わる
より高速な仕組み(VirtioFS など)の導入も進んでいる。

rm -rf /

ということなので、WSL で rm -rf / を実行すると、
Windows のファイルが削除され Windows が壊れるという話がある。

WSL2については、P9 の仕様次第。

補足(現在の挙動): WSL2 では Windows 側のファイルは
9P 越しにマウントされた別ファイルシステムであり、
rm -rf / は既定で --no-preserve-root を要求されるうえ、
マウント境界を越えないため、記事のような被害は起きにくい。
とはいえ rm -rf /mnt/c/... を明示的に叩けば
Windows 側のファイルは消えるので、
相互運用が「両刃の剣」である点は変わらない。

参考

※ 下記「kledgeb」も参照。

環境変数の共有

17063 以前

wsl がアクセスできる Windows 環境変数は PATH のみ。

17063 以降

WSLENV はブリッジのための特殊な環境変数。

C:\>set WSLENV=USERPROFILE:USERNAME
C:\>wsl
seigi@nishino:/mnt/c/Users/nishi$ echo $WSLENV
USERPROFILE:USERNAME

補足(WSLENV のフラグ): WSLENV には
変数名の後ろに / 付きのフラグを添えて
パス形式の変換を指示できる。

フラグ 意味
/p パスとして変換する(C:\foo/mnt/c/foo
/l パスのリストとして変換する(;:
/u WSL → Windows の方向のみ渡す
/w Windows → WSL の方向のみ渡す

例:set WSLENV=USERPROFILE/p:MYLIST/l

コマンド

Windows → WSL

wsl.exe を使用して CMD または PowerShell から Linux バイナリを実行

wsl.exe <command>
  • wsl でのコマンド実行と同様に処理される。

  • sudo、パイプ、ファイルリダイレクトなどが機能する。

    • バイナリ

      • ls コマンド

        wsl ls -la
        
    • パイプ

      • ls(Linux) を findstr(Windows) にパイプ

        c:\> wsl ls -la | findstr "root"
        
      • dir(Windows) を grep(Linux) にパイプ

        c:\>dir | wsl grep root
        

WSL → Windows

  • Windows バイナリには、ファイル拡張子が含まれている必要がある。

  • また、ファイルの大文字と小文字が一致している必要がある。

    • バイナリ

      • notepad

        $ notepad.exe
    • パイプ

      • ls(Linux) を findstr(Windows) にパイプ

        $ ls -la | findstr.exe "root"
        drwxr-xr-x 1 root  root    512 May  8  2018 ..
        drwxrwxrwx 1 seigi seigi   512 May  8  2018 wwwroot
      • ipconfig(Windows) を grep(Linux) にパイプ

        $ ipconfig.exe | grep IPv4
          IPv4 Address. . . . . . . . . . . : 10.0.75.1
          IPv4 Address. . . . . . . . . . . : 192.168.179.2
          IPv4 Address. . . . . . . . . . . : 172.17.68.193

補足(文字コードに注意): Windows バイナリの出力は
日本語環境では **CP932(Shift_JIS)**で返るため、
UTF-8 前提の Linux 側コマンドにパイプすると文字化けする。
ipconfig.exe | iconv -f cp932 -t utf-8 | grep ... のように
変換を挟むか、chcp.com 65001
コード ページを UTF-8 にしておく必要がある。
上記の例が英語の文字列(rootIPv4)を対象にしているのは、
この問題を避けているとも読める。

参考

kledgeb

相互運用

ファイルシステム

本 Wiki 内


Tags: Windows, Linux, Linuxサブシステム, 仮想化

⚠️ **GitHub.com Fallback** ⚠️