前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >虚拟化外设传输

虚拟化外设传输

作者头像
何其不顾四月天
发布2023-03-10 13:06:11
7000
发布2023-03-10 13:06:11
举报
文章被收录于专栏:四月天的专栏四月天的专栏

虚拟化外设传输

在虚拟化云桌面中,关于外设的使用一直有两种基本功能, 设备的透传(passthrough)与重定向(redirection).

透传:设备位于Host,将主机本身拥有的设备直接交给虚拟机使用。

重定向:远程虚拟机时,设备位于客户端,通过网络,将设备数据传递给虚拟机(guest).

设备透传(passthrough)

设备透传,主要面向IDV场景。或者说 (Host Device Pass-Through,Direct I/O).

设备透传主要依赖硬件支持,cpu/主板芯片组支持VT-D技术,软件层面/BIOS/操作系统支持IO-MMU。当前主要支持基于PCI总线透传。

当前的主要设备透传,USB设备/网卡透传/显卡透传

主要透传步骤:

代码语言:javascript
复制
#1.BIOS修改 VT-d 使能检测,未开启,则开启
#2.内核启动参数修改: intel_iommu=on
#3.查找设备地址 lspci 根据设备型号获取设备地址 lspci -n -s address 获取设备 iommu group 地址
#4.验证是否支持 iommu (dmesg |grep -i iommu|grep address) 或者 (readlink pci address)
#5.设置 SR_IOV 的 VF 端口数量
#6.解绑设备 echo "address" > /sys/bus/pci/devices/0000\:address/driver/unbind
#7.绑定设备(bind to vfio-pci) (modprobe vfio \ modprobe vfio-pci)
#8.设置启动参数 (qemu -device vfio-pci,host=address,in=net0)(libvirt 设置xml启动参数)

Egg.显卡透传:

代码语言:javascript
复制
#!/bin/bash
#

modprobe vfio
modprobe vfio-pci

dev=0000\:00\:02.0
vendor=`cat /sys/bus/pci/devices/$dev/vendor`
device=`cat /sys/bus/pci/devices/$dev/device`

systemctl restart getty@tty1.service 
#关闭显示窗口,解除进程对显卡的占用
sleep 1
rm -f /etc/apparmor.d/libvirt/libvirt-*
echo "$vendor $device" > /sys/bus/pci/drivers/vfio-pci/new_id
echo "0000:00:02.0" > /sys/bus/pci/devices/0000\:00\:02.0/driver/unbind
echo "0000:00:02.0" > /sys/bus/pci/drivers/vfio-pci/bind
echo "$vendor $device" > /sys/bus/pci/drivers/vfio-pci/remove_id

显卡回挂:

代码语言:javascript
复制
#!/bin/bash
#

echo -n "0000:00:02.0" > /sys/bus/pci/devices/0000\:00\:02.0/driver/unbind
echo -n "0000:00:02.0" > /sys/bus/pci/drivers/i915/bind
systemctl restart display-manager #重新启动显示窗口

libvirt 设备透传(鼠标为例)

  • API调用
代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <libvirt/libvirt.h>
#include <string.h>

#define MAX_LEN (1024*10)

int main(int argc, char** argv)
{
    int res;
    virConnectPtr conn;
    conn = virConnectOpen("qemu:///system");
    if(conn == NULL){
        printf("failed to open connection to qemu\n");
	return 1;
    }
    printf("success to open connection to qemu\n");
    char* xml = malloc(MAX_LEN);
    memset(xml,0,MAX_LEN);
    FILE* fp = NULL;
    fp = fopen(argv[1],"r");
    if(fp != NULL){
        int len = fread(xml,1,MAX_LEN,fp);
	printf("len = %d\n",len);
    }
    if(fp != NULL){
    	fclose(fp);
    }
    virDomainPtr dom;
    dom = virDomainDefineXML(conn,xml);
    if(!dom){
        printf("domain definition failed\n");
    } 
    char* usbxml = malloc(MAX_LEN);
    memset(usbxml,0,MAX_LEN);
    FILE* usbfp = NULL;
    usbfp = fopen(argv[2],"r");
    if(fp != NULL){
        int len = fread(usbxml,1,MAX_LEN,usbfp);
	printf("len = %d\n",len);
    }
    if(usbfp != NULL){
    	fclose(usbfp);
    }
    res = virDomainAttachDeviceFlags(dom,usbxml,VIR_DOMAIN_AFFECT_CURRENT | VIR_DOMAIN_AFFECT_LIVE);
    printf("virDomainAttachDeviceFlags res = %d\n",res);
    return 0;
}
  • xml文件
代码语言:javascript
复制
<hostdev mode='subsystem' type='usb' managed='yes'>
    <source>
        <vendor id='0x413c'/>
        <product id='0x301a'/>
    </source>
</hostdev>

设备重定向(redirection)

设备重定向通常在云桌面中使用,大体分为两种端口重定向和设备重定向。通常使用的为端口重定向,在常见的协议的中,例如spice协议。

端口重定向,通常是走总线驱动虚拟化。

设备重定向,设备驱动虚拟化。

端口重定向

以USB端口为例,下述事SPICE协议(端口重定向)的使用方法。

  • libvirt-xml文件
代码语言:javascript
复制
<!- USB2.0>
<controller type='usb' index='0' model='ich9-ehci1'/>
<controller type='usb' index='0' model='ich9-uhci1'>
  <master startport='0'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci2'>
  <master startport='2'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
  <master startport='4'/>
</controller>
<redirdev bus='usb' type='spicevmc'/>
<redirdev bus='usb' type='spicevmc'/>
<redirdev bus='usb' type='spicevmc'/>

<!- USB3.0>
<controller type='usb' index='0' model='nec-xhci'/>
<redirdev bus='usb' type='spicevmc'/>
<redirdev bus='usb' type='spicevmc'/>
<redirdev bus='usb' type='spicevmc'/>
  • QEMU
代码语言:javascript
复制
#USB2.0
-device ich9-usb-ehci1,id=usb \
-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,multifunction=on \
-device ich9-usb-uhci2,masterbus=usb.0,firstport=2 \
-device ich9-usb-uhci3,masterbus=usb.0,firstport=4 \
-chardev spicevmc,name=usbredir,id=usbredirchardev1 \
-device usb-redir,chardev=usbredirchardev1,id=usbredirdev1 \
-chardev spicevmc,name=usbredir,id=usbredirchardev2 \
-device usb-redir,chardev=usbredirchardev2,id=usbredirdev2 \
-chardev spicevmc,name=usbredir,id=usbredirchardev3 \
-device usb-redir,chardev=usbredirchardev3,id=usbredirdev3
#USB3.0
-device nec-usb-xhci,id=usb \
-chardev spicevmc,name=usbredir,id=usbredirchardev1 \
-device usb-redir,chardev=usbredirchardev1,id=usbredirdev1 \
-chardev spicevmc,name=usbredir,id=usbredirchardev2 \
-device usb-redir,chardev=usbredirchardev2,id=usbredirdev2 \
-chardev spicevmc,name=usbredir,id=usbredirchardev3 \
-device usb-redir,chardev=usbredirchardev3,id=usbredirdev3
  • remote-viewer
代码语言:javascript
复制
#自动连接
remote-viewer --spice-usbredir-redirect-on-connect="0x03,-1,-1,-1,0|-1,-1,-1,-1,1"
#热拔插时支持USB设备
remote-viewer --spice-usbredir-auto-redirect-filter="0x03,-1,-1,-1,0|-1,-1,-1,-1,1"

设备重定向

常规的重定向方法通常为端口重定向,但是例如一些设备为USB设备,但是不是使用通用USB设备,就需要使用设备重定向,需要针对开发虚拟机内部的虚拟化设备驱动,虚拟设备驱动层,但需要考虑兼容性问题,不具备通用性,成本也相对比较高。

设备重定向在应用层实现,在虚拟机上创建一个虚拟的USB外设驱动,是的应用程序获得数据。

设备重定向做为端口重定向的补充,优势时数据传输效率更高,延时更低。在使用类似于USB摄像头的场景时,就需要使用USB设备重定向或者其他特定的USB设备时,就需要使用设备重定向。

Egg:

设备重定向在实际业务场景中,还有一些其他关键因素需要考虑,设备的黑白名单,设备热拔插,还有设备重定向的需求中数据传输需要怎么做。

以摄像头为例:

代码语言:javascript
复制
#USB设备列表获取
#USB热拔插事件监听(libusb/libusbevent/libudev)
#USB黑白名单过滤
#USB重定向
#--摄像头--
#USB摄像头数据获取(视频流编码<硬编>)
#USB数据传输
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 虚拟化外设传输
    • 设备透传(passthrough)
      • 设备重定向(redirection)
      相关产品与服务
      云桌面
      云桌面(Cloud Virtual Desktop,CVD),为您提供随需快捷交付的虚拟远程桌面服务。云桌面可以帮助您轻松构建安全的数字化工作空间,满足移动办公、安全开发、教育实训、在线设计等场景需求,提升业务访问的安全性和连续性。通过自适应传输协议,终端用户可以获得优质的云桌面访问体验。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档