给 qemu 虚拟机直通 usb 设备
给 qemu 虚拟机直通宿主机的 usb 设备,可以让虚拟机直接访问 U 盘、摄像头等物理设备。
下面的步骤描述了给虚拟机直通一个 U 盘的过程。
- 获得 usb 设备的访问权限
- 把 usb 设备的所有者设置为当前用户
- 用 root 权限运行 qemu
- 设置合适的 qemu 参数并启动虚拟机
对于步骤 1,下面选择第一种方法:找到 usb 设备的路径,并把文件的所有者设置为当前用户。
获得 usb 设备的访问权限
找到 U 盘的设备路径
在 Linux 上插入一个 U 盘时,一般容易看到一个新的块设备,比如 /dev/sda 或者 /dev/sdb。但是这并不是 usb 设备本身。
通过 lsusb 命令,可以看到系统上的 usb 设备的信息。
$ lsusb
Bus 007 Device 003: ID 17ef:608c Lenovo USB Keyboard
Bus 001 Device 004: ID 17ef:608d Lenovo Optical Mouse
Bus 001 Device 005: ID 0930:6544 Toshiba Corp. TransMemory-Mini XXX 2.0 Stick
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
- 由此可知,U 盘在 bus 001,device 005 的位置。
- 可以在
/dev/bus/usb/目录中找到这个设备,就是/dev/bus/usb/001/005。通过udevadm info /dev/bus/usb/001/005可以确认这个路径指代的设备是这个 U 盘。 - 在 ID
0930:6544中,0930是 U 盘的 vendor id,6544是 product id。
设置 U 盘设备的所有者
设置 qemu 参数
为了直通前述 U 盘设备,在 qemu 命令中添加这些参数
-usb:为虚拟机开启 USB 模拟功能。vendorid=0x0930,productid=0x6544:上面找到了 U 盘的 vendor id 和 product id,依次填入。
更多信息
探索块设备 /dev/sda 和 usb 设备的关系
在系统上插入一块 U 盘,容易看到类似 /dev/sda 的块设备。从块设备可以找出 usb 设备的信息。
通过 udevadm info /dev/sda 可以看到设备的信息。
$ udevadm info /dev/sda
P: /devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda
M: sda
U: block
T: disk
D: b 8:0
N: sda
L: 0
S: disk/by-id/usb-TOSHIBA_TransMemory_8BCAA96A7EEBCE80907A4D62-0:0
S: disk/by-path/pci-0000:65:00.3-usb-0:1:1.0-scsi-0:0:0:0
S: disk/by-diskseq/21
Q: 21
E: DEVPATH=/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda
E: DEVNAME=/dev/sda
E: DEVTYPE=disk
E: DISKSEQ=21
E: MAJOR=8
E: MINOR=0
E: SUBSYSTEM=block
......
/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda 可以看到,它与 usb1/1-1 有关系。
通过 udevadm info -a 可以打印出一个设备所在的设备链条。其中就有 U 盘的 usb 设备信息。
$ udevadm info -a /dev/sda | grep 'looking at'
looking at device '/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0/block/sda':
looking at parent device '/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0':
looking at parent device '/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1/1-1:1.0/host0/target0:0:0':
looking at parent device '/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1/1-1:1.0/host0':
looking at parent device '/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1/1-1:1.0':
looking at parent device '/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1/1-1':
looking at parent device '/devices/pci0000:00/0000:00:08.1/0000:65:00.3/usb1':
looking at parent device '/devices/pci0000:00/0000:00:08.1/0000:65:00.3':
looking at parent device '/devices/pci0000:00/0000:00:08.1':
looking at parent device '/devices/pci0000:00':