由于种种原因,现在我的电脑上只保留了一个Windows。但是最近在折腾开发板,难免遇到一些要读写ext4分区的问题。不过我对Win上种种读写Ext4分区的方式抱有一种怀疑的态度,总觉它们不能正确处理permission, owner和attr等问题。
有没有更好的解决方案呢,我觉得把USB直通进Linux虚拟机/WSL2是可行的,但是问题来了,Hyper V没有USB Passhrough👎👎👎,微软似乎也没有想法给WSL2加上这个功能。辣还有没别的方法了,有的,就是我在这里要介绍的 USB/IP

USB/IP

USB/IP Project aims to develop a general USB device sharing system over IP network. To share USB devices between computers with their full functionality, USB/IP encapsulates "USB I/O messages" into TCP/IP payloads and transmits them between computers.

说白了就是把USB封装在TCP中,通过网络传送

USB/IP on Win

USB/IP官方只实现了Windows作为客户端的功能,但是我们这门这里显然是要将Windows作为服务端,不过有非官方实现的usbip-win,可以将Win作为服务端。

Win服务端安装

首先去usbip-win的Release下载最新版本,会有如下文件

  • usb.ids
  • usbip{d}.exe
  • usbip_root.inf
  • usbip_stub.{cer,inx,sys}
  • usbip_test.pfx
  • usbip_vhci.{cat,inf,sys}

将上述所有文件下载到一个文件夹中 ((怎么作者不提供一个zip包,一个个下多麻烦))

安装证书

右键usbip_test.pfx -> 安装PFX,选择“本地计算机”,而不是“当前用户”,证书密码 usbip,存储位置选择 “受信任的证书颁发机构”

开启驱动测试签名

> bcdedit.exe /set TESTSIGNING ON

然后重启系统

找到要使用的USB设备

.\usbip.exe list -l
 - busid 1-190 (0bda:565a)
   Realtek Semiconductor Corp. : unknown product (0bda:565a)
 - busid 1-160 (8087:0aaa)
   Intel Corp. : unknown product (8087:0aaa)
 - busid 1-55 (0bda:0177)
   Realtek Semiconductor Corp. : unknown product (0bda:0177)
 - busid 1-238 (2717:5010)
   unknown vendor : unknown product (2717:5010)

要找的是设备的busid 1-xxx,如果看不出来是哪个设备,把要使用的设备拔了对比一下就知道了

安装USB驱动

> .\usbip.exe install

((这里吐槽一下README在Win as Server的部分没有提这个,导致我卡了半天))

启动服务端

> .\usbipd.exe -d -4

HyperV客户端

以我所使用的发行版fedora为例

安装模块

sudo dnf makecache && sudo dnf update
sudo dnf install usbip
sudo reboot

重启之后sudo modprobe vhci-hcd加载usbip驱动,当然也可以写进/etc/modules

连接USB设备

sudo usbip attach -r <Your Server IP> -b <Your Device Busid>
lsusb
dmesg | tail

如果驱动正确的话(指这个USB设备所对应的驱动),就能按照正常使用USB设备一样使用了

WSL2客户端

不同于WSL1翻译API的方案,WSL2使用了虚拟机的方案。正因如此,WSL2可以折腾的东西比WSL1多的多,比如我们这次需要用的更换内核。因为VHCI_HCD没有编译进WSL2的内核,而且也不能用发行版的Linux Modules,我们只有自行编译内核。

首先从 WSL2-Linux-Kernel 的tag 中找到你使用的内核版本 (uname -r) 对应的tag的源码archive, 也可以git fetch && git checkout,但那样下载的时间可能更长一些。进入源码目录

sudo apt install build-essential flex bison libssl-dev libelf-dev
cp Microsoft/config-wsl ./.config
make menuconfig

这里要自己配置config,我不放我配置好了的.config了,因为可能内核版本不一样,配置也不一样,说一下怎么配置。 WSL2 的内核默认没有加入 USB 驱动,所以需要开启

Device Drivers
---> USB Support
     ---> Support for Host-side USB
          ---> USB/IP Support
               ---> VHCI hcd
               ---> Host driver

你一定注意到了,当你开启Support for Host-side之后,多出了许多了选项,这些很多是对应某种USB设备驱动,比如 USB Mass Storage Support是对应USB大容量存储设备(U盘), USB Wireless Device Management support 是USB无线网卡的驱动, USB Serial Converter support是USB转TTL设备的驱动。根据你所需要直通的设备,你要将相应的驱动也一并打开。

配置完之后

make -j$(nproc)
# 编译
make bzImage
# 生成启动镜像
make modules
sudo make modules_install
# 编译和安装模块

然后将wsl2的内核替换成我们刚刚编译好的

mkdir <WinHome>/Documents/kernel
cp arch/x86/boot/bzImage <WinHome>/Documents/kernel
echo><winhome>/.wslconfig<<EOF
[wsl2]
kernel=C:\\Users\\<Username>\\Documents\\kernel\\bzImage
EOF

退出wsl,并wsl --shutdown,之后重新打开wsl, 使用 dmesg| grep vhci 即可验证USB/IP驱动是否正确加载。

至于如何连接USB设备,前文已经说过了,就不再赘述了

Update

遇到了无法unbind的问题,并且每次设备插入,都会默认USBIP的驱动,这个时候请进入设备管理器,删除USBIP的设备(并卸载驱动)


作死更新了 Fast Ring,然后没出一个月 Windows 就挂了 T_T, 重新拥抱 Unix ,现在用的 macOS + Linux