👻

WSL2上のLinuxでUSBストレージデバイスを使う

2022/11/28に公開

WSLでUSBメモリとかを使いたい

いつ頃かは知りませんが,OSSのusbipd-winを利用して,WSL2上のLinuxにUSBデバイスを共有できるようになってたみたいですね.

Windows11のWSL標準Linuxカーネルには,既にUSBIPのモジュールが組み込まれているみたいです.なので単に接続するだけであれば,USBIPホストとクライアントの設定だけで利用できます.ただ,USB Mass Storage Driverが標準カーネルに組み込まれていないので,ストレージデバイスとして使いたい場合は独自にビルドしたカーネルを使用する必要があります.

Windows10の場合はUSBIPのモジュールもデフォルトで組み込まれていないようなので,これも独自にビルドする必要があるようですね.

備忘録がてら手順を残しておきます.(少し癖のある環境なのでアテにならないかもしれない…)

あとZennで物書くのは初めてなんでお手柔らかに…

(特に断りがない場合,表記しているコマンド類はWSL or Linux環境で実行するものです)

使用環境

  • Windows 11 Pro 22H2 (x64)
  • WSL (Version 1.0.0, MS Store版)
    • Distribution: Arch Linux (ArchWSL 22.10.16.0, WSL2)
    • Kernel: 5.15.74.2-microsoft-standard-WSL2

要件

基本はMicrosoftのドキュメントの要件を満たしていればOKです.

Linuxカーネルのビルドをするので,ある程度リソースに余裕のあるWSLか普通のLinux環境があると望ましいです.ここでは既存のWSL上でそのままビルドします.

Linuxカーネルのビルド・変更

依存パッケージの導入

カーネルビルドに必要なパッケージを調べて,先に導入しておきます.
Linuxの公式ドキュメントに最低限必要なプログラムのリストがありますが,<ディストリビューション名> kernel build requirementsとかでググれば,パッケージマネージャのコマンドごと出てくると思います.

Ubuntuの依存パッケージはWSL2カーネルのREADMEにありますね.

自分のArchLinux環境ではとりあえずこれで通りました.(pacmanラッパーのyayを使ってるので,適宜pacmanなりに読みかえてください)

Shell
yay -S base-devel asp pahole

足りないときはビルド時にエラーが出ますが,大抵どのプログラムがない等が出力されるので,それを見て対応すればOKです.

リポジトリのクローン

WSL2カーネルのリポジトリをクローンします.

https://github.com/microsoft/WSL2-Linux-Kernel

Shell
git clone https://github.com/microsoft/WSL2-Linux-Kernel.git

トータルで3~4GBくらいあるんで,ストレージに余裕のない方は注意した方が良いです.

Build Configuration

いくつかやり方はありますが,ここではデフォルトのconfigをコピーしてきて,menuconfigで変更します.

  1. クローンしたディレクトリのルートで,以下を実行します.
Shell
cp ./Microsoft/config-wsl ./.config
make menuconfig
  1. このようなTUIが出てきます.十字キーと<Enter>で操作します.
    menuconfig
    menuconfig
    Device DriversUSB Support と進み,USB Mass Storage support を探します.

    Device Drivers

    USB Support

    USB Mass Storage support
    これを選択した状態で,Yを押します.すると項目左側のカッコに*が表示され,ドライバが有効になります.
    こんな感じ
    こんな感じ
    基本的にはこれでOKですが,別途特別なドライバが必要な場合はここで一緒に有効にしておきます.心当たりがなければ,このままで問題無いです.

  2. 変更したConfigを保存します.左右キーで下側のコマンドのカーソル(画像参照)を動かし,Saveを選んでEnterを押します.

    Save
    保存するファイル名を聞かれますが,特に変更の必要もないのでそのままEnterでOKです.

Optional: Local versionの変更

General SetupLocal version から,Local version名の変更が可能です.uname -aとかで確認したときに出てくるやつですね.
そのままでも問題無いですが,オリジナルと区別できるように適当に変えておくと良いでしょう.

デフォルトは-microsoft-standard-WSL2です.


Local version

  1. 同様にExitを選択して終了します.

ビルド

以下のコマンドでビルドします.

Shell
make -j $(nproc)

何回もカーネルのビルドを経験してると最早気になりませんが,貧弱なCPUだと結構時間がかかります(特にラップトップとかはクロックでないので…).筆者のデスクトップで4分程度,ラップトップでは十数分かかりました.
-jオプションを付けないと単一ジョブで走るので,更に遅くなります.

参考までにビルドした環境も載せときます.WSLで利用できるリソースに制限をかけているので,フルパワーの時より劣る結果にはなっています.

ビルド環境
  • デスクトップ
    • CPU: Intel Core i7-12700K 12C/20T 8コア制限
    • RAM: DDR5-5200 64GB 16GB制限
  • ラップトップ
    • CPU: Intel Core i7-8750H 6C/12T 6コア制限
    • RAM: DDR4-2666 16GB 8GB制限

特に設定をいじっていなければ,CPUは搭載の全コア,メモリは全体の80%上限だったと思います.

完成したカーネルは,vmlinuxという名前でディレクトリのルートにいます.

Shell
ls -lh vmlinux 
-rwxr-xr-x 1 nanami nanami 808M Nov 28 01:39 vmlinux

ちなみに,ビルド後はArtifactで +4GB 程度ストレージを圧迫するので注意してください.

Shell
du -sh
7.1G    .

カスタムカーネルに変更

.wslconfigで作成したカーネルを指定し,WSLで使われるカーネルを差し替えます.この操作はWSLの全ディストリビューションに対して有効です.

  1. vmlinuxをWindows側のファイルシステムへコピー
    置き場所はWindows側のファイルシステム上であればどこでも良いです.
    わかりやすい場所が良いので,Cドライブ直下などにディレクトリを作るのがベターでしょう.
    併せて適当にリネームもしています.
Shell
mkdir -p /mnt/c/wsl
cp ./vmlinux /mnt/c/wsl/515-microsoft-nanamiiiii-WSL
  1. (作成していない場合) %USERPROFILE%直下に.wslconfigファイルを作成する
    %USERPROFILE%はユーザーディレクトリ,つまりC:\Users\username直下のことです.

    .wslconfig

  2. .wslconfigにカーネルの設定を書き込む
    .wslconfigini形式の設定ファイルで,全WSL環境で共通の設定になります.
    ここでkernelに先ほどコピーしたvmlinuxへのパスを指定します.
    \はエスケープをしないと正しく解釈されません

[wsl2]
kernel=C:\\wsl\\515-microsoft-nanamiiiii-WSL

WSLを再起動

以下はPowershell等Windows側のシェルから実行してください.
筆者はNushellを使用しています.

Powershell
wsl --shutdown
wsl

これで正常にWSLが立ち上がれば完了です.uname -aでVersion Stringを確認すると,変化していることが分かります.

uname -a

usbipd-winのインストール

https://github.com/dorssel/usbipd-win
上のリポジトリのReleaseより,最新のmsiをダウンロード・インストールします.

wingetでもインストールできます.

Powershell
winget install --interactive --exact dorssel.usbipd-win

PATHを反映するため,ここで再起動しておくと良いでしょう.

LinuxにUSBIPクライアントをインストール

ここもディストリビューションによって異なるので,自身の環境にあった導入をしてください.
Ubuntuの場合はMicrosoft公式Docsに記載があります.

筆者環境(ArchLinux)の場合は以下でOKです.

Shell
yay -S usbip

USBストレージを接続

WSLのシェルを開いた状態で,別に管理者権限のPowershell (or その他Windowsのシェル) も立ち上げておきます.

Tips: Windowsのsudo

WindowsでもLinuxのsudoのように,一般ユーザーから管理者権限へ昇格してコマンド実行ができる方法が存在します.
Powershellスクリプトでゴニョゴニョしたり,外部ツールを入れたりなどいくつかありますが,以下の記事の方法が一番簡単でしょう.
https://zenn.dev/ryuu/articles/wanttousesudo-with-win

これを導入すると,sudo <command>を打つことでUACダイアログが現れ,管理者権限でコマンドを実行できます.

  1. Windowsのシェルから,接続可能なUSBデバイスをリストアップします
Powershell
usbipd wsl list


usbpid wsl list
ただここではUSB Mass Storage Deviceとしか表示されないので,接続したいデバイスが特定できない場合があります.そのときは,USBデバイスのプロパティへ飛び,ParentのVID:PIDとシェルに現れたVID:PIDを照合することで特定できます.

Device Properties
この画像の場合,VID:PID8564:1000のデバイスがParentにあたるので,BUSID:1-8のデバイスをWSLにアタッチします.

  1. BUSIDを指定してデバイスをWSLにアタッチ
    オプション-bBUSIDを指定します.
    WSLにアタッチしている間,そのデバイスにはWindows側からアクセスできないので注意してください.
Powershell
usbipd wsl attach -b 1-8


STATEがAttachedに変化

  1. WSL側で確認
    lsblkfdiskで,USBストレージが読み込まれていることを確認します.lsusbでは認識されているのにこれらのコマンドで現れない場合は,Mass Storage Driverが読み込まれていない可能性が高いです.

    lsblk

ここからは,通常のLinuxの場合と同様に扱うことができます.個人的にはddでフラッシュメモリにイメージを焼くときに重宝してます.

作業が終わったら…

WSLからデタッチして,Windows側に戻します.同じく管理者権限のPowershellで以下を実行します.

Powershell
usbipd wsl detach -b 1-8
# STATEがNot Attachedとなっているのを確認する
usbipd wsl list


Not Attachedに戻っている

おわりに

大したことをやっているわけではないですが,慣れない人からすれば面倒な点がいくらかあるかと思ったので,少し丁寧に書きました.

自分は組み込みデバイスのFWフラッシュやシリアルコンソール,JTAGデバッガなどをよく使うので,この機能は重宝しています.

間違いや指摘などあれば気軽に教えていただけると助かります.

Discussion