☰
USB虚拟化实战:透传、USB over IP与Gadget排错
2026/9/30 5:07:22 网站建设 项目流程

做嵌入式和虚拟化运维这行,被问得最多的一类问题,不是"内核怎么编译",而是"我的 USB 设备在虚拟机里就是不认"。U盘插上没反应、USB 转串口在客户机里反复掉线、下载器一跑就断、加密狗第一天好好的第二天罢工——这些现象的根子,往往都指向同一件事:USB 虚拟化做得对不对。这篇就把我这些年踩过的坑、测过的方案、以及那些文档里不会写的细节,系统性地摊开讲一遍,从 USB 协议本身为什么难虚拟,到 KVM、VMware、Hyper-V 上的透传实操,再到 USB over IP、设备端 gadget 虚拟化、抓包排错和安全白名单。不管你是刚接触虚拟化的运维,还是天天跟 STM32、Zynq 打交道的嵌入式工程师,应该都能从里面找到能直接抄的配置和能少走的弯路。

1. USB虚拟化到底在虚拟什么:先拆清协议,再谈方案

很多人一上来就问"哪个软件能虚拟 USB",这个问题本身就问偏了。USB 虚拟化不是一个功能,而是一组技术,不同的场景解决的是完全不同的问题。不先把概念分清,后面选型一定翻车。

1.1 三类被混为一谈的"USB虚拟化"

我见过的需求基本可以归到下面四类,它们的技术路径差得很远:

类型典型场景本质代表实现
主机侧透传虚拟机用物理U盘、加密狗把宿主机的物理设备直接交给客户机驱动QEMU usb-host、VMware USB Pass-through
远程重定向云桌面映射本地串口将 USB 请求(URB)打包走网络USB/IP、usbredir
设备端虚拟化一块板子模拟成U盘/串口/HID设备控制器(UDC)软件模拟Linux USB Gadget、STM32 USB Device
纯软件模拟虚拟机里凭空多个键盘无真实硬件,纯模型QEMU 模拟 HID、U盘

透传是"把真东西借出去",重定向是"把信号传过去",gadget 是"把板子装成别人",纯模拟是"无中生有"。这四类的排错思路完全不同:透传失败看宿主机是否抢占,重定向失败看网络和协议,gadget 失败看描述符和枚举,纯模拟失败看 QEMU 参数。

1.2 必须被"保真"传递的:描述符、端点、传输类型

USB 是典型的主从轮询式总线,主机发话,设备应答。虚拟化要做的核心工作,就是把设备的"自我介绍"原封不动地递到客户机面前。这套自我介绍就是描述符层级:

  • 设备描述符:idVendor、idProduct、bcdUSB、bMaxPacketSize0
  • 配置描述符:供电方式、最大功耗、接口数量
  • 接口描述符:bInterfaceClass(CDC、HID、MSC、UAC 等)
  • 端点描述符:端点地址、方向、传输类型、wMaxPacketSize、bInterval

透传时如果这段信息被宿主机的驱动"加工"过,客户机拿到的就是残缺描述符,表现就是"识别成未知设备"。所以一个铁律是:透传走的必须是原始 USB 层,而不是宿主机已经枚举并绑定驱动的设备节点——这一点后面 QEMU 和 usbipd 的选择上会反复提到。

传输类型则决定了虚拟化能否胜任:

  • 控制传输:枚举、命令,延迟不敏感,几乎都能虚拟
  • 批量传输:U盘、打印机,带宽敏感但对抖动容忍
  • 中断传输:键鼠、HID,依赖轮询间隔 bInterval
  • 等时传输:音频、摄像头,对时序和抖动极度敏感,最容易被虚拟化毁掉

1.3 为什么USB这么难虚拟:从微帧和高速握手说起

USB 全速是 12 Mbps,高速是 480 Mbps,低速 1.5 Mbps。高速模式下,主机每125 微秒发一个微帧;等时传输就挂在这套时间框架里。透传引入的任何延迟抖动,都会让等时流出现爆音或掉帧,这跟网络带宽够不够是两码事——是时间精度问题。

再一个是高速握手:设备接入后,主机会先复位,设备通过 chirp K/J 序列申请切换到高速。这个过程是硬件层面的电气协商。当你把设备透传给虚拟机,宿主机控制器已经完成了握手,虚拟机里的虚拟控制器并不需要重新协商,QEMU 会把协商结果直接呈现给客户机。这也解释了为什么有些设备透传后"速度档位"不对——它按全速而非高速被呈现了。

理解了这三点,你就能预判:U盘基本都能透传,音频和摄像头透传要看平台,而需要精确时序的下载器尽量别走远程。下面是具体平台的实操。

2. 主流虚拟化平台的USB透传:QEMU、VMware、Hyper-V怎么选

选平台本质上是在选"谁来完成枚举的接管"和"延迟有多低"。我把三种最常用的方案拆开讲,包括那些只在出问题时才会暴露的参数。

2.1 QEMU的两个入口:usb-host和usb-redir

QEMU 提供了两条完全不同的路:

  • usb-host:宿主内核通过usbfs把设备暴露给 QEMU,QEMU 直接跟设备对话,性能最好,本地透传首选。
  • usb-redir:走 usbredir 协议,设备经网络传到 QEMU,配合 SPICE 常用,适合远程桌面场景。

usb-host 的关键在于设备定位方式,我强烈建议用总线号和端口号,而不是 vendor:product:

# 不推荐:同型号设备多个时会抓错 -device usb-host,vendorid=0x0403,productid=0x6001 # 推荐:按物理端口锁定,稳定可复现 lsusb -t # 先看清楚 bus 和 port -device usb-host,hostbus=1,hostport=4

为什么?想象你有一排十个 FT232 串口插在同一个扩展坞上,vendor:product 完全一样。用 ID 匹配,QEMU 可能把第 3 个当成第 1 个给你,串口号全乱。按hostbus/hostport锁定,插哪个口就是哪个设备,这是我在产线测试环境里用命换来的经验。

2.2 libvirt里手写hostdev:路径匹配的坑

用 libvirt 管理时,配置在<hostdev>里写。同样推荐用地址而不是 ID:

<hostdev mode='subsystem' type='usb' managed='yes'> <source> <address bus='1' port='4'/> </source> </hostdev>

managed='yes'让 libvirt 自动在透传前把设备从宿主机驱动上解绑、透传后再绑回。如果这里报错,八成是宿主机某个服务(比如 ModemManager、usbguard)在设备一插入时就抢走了,导致解绑失败。解决办法是给设备加 udev 规则,把宿主机对该设备的自动绑定屏蔽掉。

还有一个高频现象:USB 设备热插拔后 bus/port 变了(换到别的口),XML 里写死的地址失配,虚拟机里就再也看不到设备。要么固定插口,要么改用vendor/product加allow过滤,二选一,别指望它自动跟。

2.3 VMware的USB仲裁:为什么它总"抢"

VMware Workstation 有一整套 USB 仲裁机制(Windows 上是vmware-usbarbitrator服务在管)。它的问题不在能不能透传,而在"抢得太积极":U盘一插,宿主机和虚拟机都想接管,结果两边驱动打架。

我的标准做法是:

  1. 在虚拟机设置里勾选显示所有 USB 输入设备;
  2. 配置"自动连接"规则时,明确指定新 USB 设备连接到虚拟机还是宿主机;
  3. 客户机内装好对应驱动,尤其是 USB 转串口这类需要厂商 VCP 驱动的设备。

Windows 客户机里,如果设备管理器里出现一个带感叹号的"其它设备"或反复刷新,通常是宿主机已经绑定了驱动,客户机拿不到原始描述符。这时先把宿主机侧的厂商驱动卸载(保留系统自带的通用枚举),再插上让它透传,客户机里再装驱动,顺序反了就是白费劲。

2.4 "USB资源不足"背后是控制器端口耗尽了

这个报错在 QEMU 和 VMware 上都常见。根因不是主机 USB 口不够,而是虚拟机内部的虚拟 USB 控制器端口用满了。

QEMU 默认可能只配了一个 UHCI/EHCI 控制器,端口数量有限。解决办法是按需增加控制器,并明确指定是 USB 3.0(xHCI)还是 2.0:

-device qemu-xhci,id=xhci,p2=8,p3=8 # 给足够多的 2.0/3.0 端口 -device usb-host,bus=xhci.0,hostbus=1,hostport=4

一个 xHCI 控制器能挂的端口有限,设备一多就得加控制器实例。这也是为什么有人明明只透传了两个设备却报资源不足——他透传的是组合设备(比如带复合接口的 HID),一个物理设备占用了多个虚拟端口。

3. USB over IP与终端虚拟化:让串口和加密狗跨越物理机

本地透传解决"同一台机器",但企业里更常见的需求是"设备在这栋楼,虚拟机在那栋楼"。这就是 USB over IP 和云桌面 USB 重定向的地盘。

3.1 USB/IP协议的组成与usbipd-win

USB/IP 把 USB 请求块(URB)在网络上传输。它由两端组成:

  • 服务端:运行usbipd,导出物理设备;内核模块usbip-host
  • 客户端:内核模块vhci_hcd造一个虚拟主机控制器,把远程设备挂上来

Linux 上的经典命令:

# 服务端:查看并绑定可导出的设备 usbip list -l usbip bind -b 1-4 # 客户端:查看远程设备并挂载 usbip list -r 192.168.1.100 usbip attach -r 192.168.1.100 -b 1-4

而在 WSL2 场景里,微软官方推的是usbipd-win:Windows 侧跑服务,把设备共享给 WSL2 的 Linux 内核,然后利用 WSL2 自带的 USB/IP 客户端挂载。命令大致是:

# Windows 侧(管理员) usbipd list usbipd bind --busid 1-4 usbipd attach --wsl --busid 1-4

这一步的前提是 WSL2 本身能起来,而 WSL2 依赖硬件虚拟化。如果启动时报虚拟化未启用,那是 BIOS/UEFI 里的虚拟化开关和 Windows 侧"基于虚拟化的安全性"(VBS)占用了 hypervisor 导致的,属于平台配置问题,得先把底层虚拟化环境理顺,USB 的活儿才谈得上。

3.2 云桌面里的USB映射策略:设备级还是端口级

在终端虚拟化/云桌面(Citrix、各类 VDI 方案)里,USB 重定向一般有两种粒度:

  • 设备级重定向:整个设备映射到虚拟桌面,客户机拿到完整设备,兼容性最好,但要求网络稳定。
  • 端口级/协议级重定向:只把串口数据流抽象成虚拟 COM 口转发,性能好、带宽低,但丢掉了 USB 原生语义,遇到需要精确控制的加密狗或专用设备就失效。

选择原则很简单:加密狗、专用采集卡走设备级;普通扫码枪、普通串口走协议级。加密狗这类设备对时序和握手敏感,协议级抽象常常导致"许可证无效",因为厂商的加密逻辑依赖底层 USB 交互。

3.3 哪些设备适合远程映射,哪些千万别

设备类型传输类型远程映射建议
U盘/存储批量可以,注意带宽
USB转串口中断+批量很适合,延迟容忍度高
加密狗控制+中断可用,需设备级,测试验证
USB麦克风等时不建议,容易爆音
USB摄像头等时不建议远程
JTAG下载器控制+批量不建议,时序敏感

网络抖动对等时传输是致命的。本地透传时 USB 的时间精度就够勉强了,再叠加一层网络,音视频基本没救。这不是配置能解决的,是物理规律。

4. 设备端视角:把开发板虚拟成USB设备

前面都是从主机角度讲,但嵌入式圈子里的"USB 虚拟化"经常指另一件事:让 MCU 或者 Zynq 之类把自己模拟成某个 USB 设备。这是 USB Gadget 的领域。

4.1 MCU做USB设备:描述符和枚举是重灾区

STM32、Zynq 裸机下做 USB 从机,最容易翻车的不是代码逻辑,而是描述符写错导致枚举失败。枚举过程大致是:

  1. 主机复位设备,设备在地址 0 应答;
  2. 主机GET_DESCRIPTOR拿设备描述符前 8 字节,知道端点 0 包长;
  3. 主机分配新地址SET_ADDRESS;
  4. 主机读完整配置描述符;
  5. SET_CONFIGURATION使能端点,枚举完成。

任何一个描述符的长度字段对不上(比如配置描述符里wTotalLength少算了接口和端点),主机就会直接中断枚举。这也是"圈圈教你玩USB"那类教程反复强调描述符的原因——它是协议的地基。

另外常被问的:MCU 没有 USB 差分信号引脚怎么办?很多低成本 MCU 根本没有原生 USB PHY,或者差分引脚被占用了。常见的替代思路是外挂一个 USB 转串口芯片(CH340、CP2102N、FT232 之类),把 MCU 的 UART 桥接到 USB,对主机呈现为一个虚拟 COM 口。虽然这不是严格意义的"USB 设备虚拟化",但对功能而言是高效解法。

4.2 转串口驱动在虚拟化环境的安装顺序

FT232R、FT231X、CP2102N、CH340 这几种芯片在虚拟机里最容易出问题。它们各自需要不同的驱动,而且安装顺序错了必炸:

芯片官方驱动虚拟化注意点
FT232R / FT231XFTDI VCP透传前先卸宿主机FTDI驱动,让原始枚举透传
CP2102NSilicon Labs VCP客户机装驱动后再插设备
CH340/CH341沁恒驱动Windows下免驱常失效,需手动装
Z-TEK力特 USB转232随芯片而定认准芯片型号再下驱动

正确顺序是:宿主机确认不绑定厂商驱动 → 透传设备 → 客户机内安装 VCP 驱动 → 验证 COM 口。反过来的话,宿主机把设备绑定了,透传给客户机的就是残缺设备,客户机里怎么装驱动都是感叹号。

一个实操细节:Windows 10/11 对 FTDI 设备的驱动匹配很激进,会自动装一个"USB Serial Converter"。如果虚拟机里想要的 COM 口号被宿主机占着,先在宿主机设备管理器里把该设备禁用(不是卸载),透传后再释放。

4.3 USB Blaster、Platform Cable这类下载器为什么在虚拟机里总掉

FPGA 工程师的痛点。USB Blaster(Altera/Intel)、Xilinx Platform Cable 这类 JTAG 下载器,本质上是对时序敏感的中断+批量设备,透传一旦引入抖动,就表现为:

  • 编程烧录中途断开;
  • 反复 "USB firmware loader" 加载失败;
  • 客户机报无法加载硬件驱动。

原因有两层:一是 JTAG 时序容差小,透传延迟吃不消;二是 Windows 客户机里跟宿主机抢设备的进程多。我的建议是:

涉及 FPGA 烧录、量产烧写这类操作,优先用物理机或给虚拟机做 USB 控制器的 PCIe 直通(把整个 xHCI 控制器直通给虚拟机),而不是设备级透传。整控制器直通绕开了 QEMU 的逐设备模拟,时序问题少一大半。

5. 让看不见的总线可观测:抓包、排错与安全

USB 排错最痛苦的地方在于"看不见"。设备管理器只告诉你"未知设备",具体哪一步枚举失败的,得靠抓包和内核日志。

5.1 Wireshark配USBPcap:过滤器和描述符怎么看

Windows 上装 USBPcap,Wireshark 就能抓到 USB 流量。关键过滤器:

usb.device_address == 5 # 只看某个地址的设备 usb.transfer_type == 0x02 # 只看批量传输 usb.bDescriptorType == 0x02 # 只看配置描述符

抓包时最有价值的是枚举阶段:看GET_DESCRIPTOR的应答、SET_ADDRESS、SET_CONFIGURATION,能直接定位是描述符不合法还是请求无响应。注意 USBPcap 只能抓宿主机侧的流量,设备一旦透传进虚拟机,宿主机就抓不到了——要在客户机里装抓包环境,或者做控制器直通后在外层抓。

5.2 枚举失败的完整排查链路

我通常按这个顺序走,从底到上:

# 1. 内核是否看到设备 dmesg | grep -i usb # 2. 拓扑和速度档位 lsusb -t # 3. 详细描述符 lsusb -v -d 0403:6001 # 4. 是否被驱动占用 usb-devices | grep -A5 FTDI

第一步dmesg就能筛掉一半问题:如果日志里根本没有新设备,说明电气层或控制器就没识别,跟虚拟化无关。如果看到了设备但lsusb -v读描述符报错,那是设备或线材问题。如果宿主机识别正常但客户机不行,才轮到虚拟化配置背锅。

Windows 客户机侧对应地看设备管理器和事件查看器。那个常被吐槽的 "WD SES Device" 实际上是西数移动硬盘的加密/管理接口,跟透传无关,别被它带偏。

5.3 用usbguard给USB虚拟化加一道安全闸

USB 是攻击面最广的接口之一——BadUSB 那类伪装成键盘的设备至今有效。在服务器和虚拟化宿主上,我建议上usbguard做白名单:

usbguard list-devices usbguard allow-device 4 usbguard generate-policy > rules.conf

规则可以按 vendor、product 甚至序列号放行。这样插进来一个没登记的 U 盘,默认是拒绝的。注意 usbguard 会和 libvirt 的managed='yes'抢设备,所以要在规则里给待透传的设备放行,否则透传必失败——这俩的冲突我吃过不止一次。

5.4 Web Serial这类新玩法与虚拟化的关系

浏览器里的 Web Serial API 让网页直接读写串口,很多人拿它做在线烧录、设备调试。它的底层还是要枚举 USB 转串口设备。如果这台上位机本身跑在虚拟机里,Web Serial 能不能用,取决于虚拟化层把串口设备透传得是否干净——设备级透传通常正常,协议级重定向就未必,因为浏览器拿到的是虚拟 COM 口,握手细节可能缺失。Android USB 通信、STM32 的 DFU 升级也同理,客户端能不能拿到完整的 USB 语义,是成败关键。

6. 我个人在长期实操中的几点体会

折腾了这么多环境,有几个经验我觉得比任何单条命令都值钱。第一,永远优先按物理端口定位设备,vendor:product 匹配在设备一多的时候就是灾难制造机。第二,透传的成败很多时候在插设备之前就决定了,宿主机的驱动绑定、usbguard 规则、仲裁服务,这些都要提前清理干净,等出问题了再查,成本翻几倍。第三,时序敏感的设备别硬上虚拟化,FPGA 下载器、音视频采集、精确计时的仪器,能用物理机或控制器直通就别省这点硬件钱,稳定性是用真金白银换来的。第四,抓包是 USB 排错的终极大招,学会看枚举阶段的请求应答,比在论坛上问一百遍都管用。这些内容后续还可以往 PCIe 直通、SR-IOV 这些更底层的方向延伸,如果大家对整控制器直通的配置细节感兴趣,我下次可以单独拉一篇讲 QEMU 的 VFIO 绑定和 IOMMU 分组。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询