赞
踩
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
效率问题
在传统的完全虚拟化环境中,虚拟化系统必须捕捉这些请求,然后模拟物理硬件的行为。尽管这样做提供很大的灵活性(即运行未更改的操作系统),但它的效率比较低。
在传统虚拟化系统中,会使用QEMU通过纯软件的方式来模拟I/O 设备,包括键盘、鼠标、显示器,硬盘和网卡等。
缺点
不同的虚拟化解决方案都会给操作系统带来负担,负担的大小取决于各个解决方案的需求。其中的一项开销为设备的虚拟化。
每次I/O 操作的路径比较长,需要多次上下文切换,也需要多次数据复制,所以性能较差。
虚拟化环境必须使用客户操作系统自身的驱动感觉不到自己运行在虚拟机上,不然让客户操作系统开发人员编写大量代码同样不是一个很好的设计方案,因此虚拟化系统需要提供抽象设备,抽象设备实现了针对特定设备类的高级接口,目前比较高效的设备虚拟化接口是Virtio。
通过使用Virtio,客户操作系统包含了充当前端的驱动程序,虚拟化系统为特定的设备模拟实现后端驱动程序。通过在这些前端和后端驱动程序中的 virtio,为开发模拟设备提供标准化接口,从而增加代码的跨平台重用率并提高效率。
virtio 省去了纯模拟模式下的异常捕获环节,客户操作系统可以和QEMU 的I/O 模块直接通信。
在完全虚拟化的解决方案中,guest VM 要使用底层 host 资源,需要 Hypervisor 来截获所有的请求指令,然后模拟出这些指令的行为,这样势必会带来很多性能上的开销。
由于不同 guest 前端设备其工作逻辑大同小异(如块设备、网络设备、PCI设备、balloon驱动等),单独为每个设备定义一套接口实属没有必要,这个时候,就需要一套通用框架和标准接口(协议)来完成两者之间的交互过程,virtio 就是这样一套标准。
从总体上看,virtio 可以分为四层,包括前端 guest 中各种驱动程序模块,后端 Hypervisor (实现在Qemu上)上的处理程序模块,中间用于前后端通信的 virtio 层和 virtio-ring 层,virtio 这一层实现的是虚拟队列接口,算是前后端通信的桥梁,而 virtio-ring 则是该桥梁的具体实现,它实现了两个环形缓冲区,分别用于保存前端驱动程序和后端处理程序执行的信息。
virtio 和 virtio-ring 可以看做是一层,virtio-ring 实现了 virtio 的具体通信机制和数据流程。或者可以说,virtio 层属于控制层,负责前后端之间的通知机制(kick,notify)和控制流程,而 virtio-ring 则负责具体数据流转发。
KVM/QEMU 的 vitio 实现采用在 Guest OS 内核中安装前端驱动 (Front-end driver)和在 QEMU 中实现后端驱动(Back-end)的方式。前后端驱动通过 vring 直接通信,这就绕过了经过 KVM 内核模块的过程,达到提高 I/O 性能的目的。
Front-end
A kernel module in guest OS
Accepts I/O requests from user process
Transfer I/O requests to back-end
Back-end
A device in QEMU
Accepts I/O requests from front-end
Perform I/O operation via physical device
前端 VirtIO 驱动程序存在于客户机的内核中,后端 VirtIO 设备存在于管理程序(Qemu)中,它们之间的通信通过 VirtQueues & VRings 在数据平面中处理。
来自 VirtIO 驱动程序和设备的通知(例如 VMExits、vCPU IRQ),这些通知被路由到 KVM 中断。
desc
:用于存储一些关联的描述符,每个描述符记录一个对 buffer 的描述
available ring
:则用于 guest 端表示当前有哪些描述符是可用的
used ring
:则表示 host 端哪些描述符已经被使用
Virtio 使用 virtqueue 来实现 I/O 机制,每个 virtqueue 就是一个承载大量数据的队列。
具体的,假设 guest 要向 host 发送数据,首先,guest 通过函数 virtqueue_add_buf 将存有数据的 buffer 添加到 virtqueue 中,然后调用 virtqueue_kick 函数,virtqueue_kick 调用 virtqueue_notify 函数,通过写入寄存器的方式来通知到 host。host 调用 virtqueue_get_buf 来获取 virtqueue 中收到的数据。
Host 数据发到 Guest:
Guest OS 中,在不使用 virtio 设备的时候,这些驱动不会被加载。只有在使用某个 virtio 设备的时候,对应的驱动才会被加载。每个前端驱动器具有在管理程序中的相应的后端的驱动程序。
在virtio-blk磁盘中,采用io_write函数将virtqueue的编号写到相应的寄存器,导致虚拟机退出,进行前端到后端通知,采用中断注入方式实现后端到前端的通知,并通过IO环(vring)进行数据的共享,IO模型也随之发生变化。
参考链接:https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.qavf.overview/topic/virtfs_arch.html https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.qavf.overview/topic/socket_arch.html
通过虚拟化,Android Automotive OS (AAOS) 的单个或多个实例可以作为GuestOS与其他汽车操作系统一起运行。这可通过 VirtIO来实现,可让 AAOS 针对通用虚拟化平台运行,进而使 AAOS 客户机虚拟机能够在不同的 Hypervisor 系统或硬件平台之间移植。
AAOS 平台团队已使用 BlackBerry QNX 的 QNX Hypervisor for Safety 在 Qualcomm SA8155P 芯片组上开发并验证初始参考平台版本 trout 1.0。
AAOS 中为支持 VirtIO 所需进行的大部分更改都涉及到 Android 通用内核中 HAL 实现级别及以下级别的更改。Android 框架使用 AAOS 客户机虚拟机内核中的 VirtIO 驱动程序与一个与硬件无关的通用 HAL 进行通信,而 VirtIO 驱动程序使用 VirtIO 协议与主机端的 VirtIO 设备进行通信。主机端的 VirtIO 设备可以使用 SoC 专用设备驱动程序来访问物理硬件。
当 AAOS 作为客户机虚拟机与其他汽车操作系统一起运行时,Android 可能无法直接访问传感器。在这种情况下,Android 客户机虚拟机上的 Virtio-SCMI 驱动程序和主机虚拟机上的 VirtIO-SCMI 设备用于访问传感器。AAOS 虚拟化参考平台提供了一个与硬件无关的通用传感器 HAL,它可用于基于 ARM 的 SoC 以访问传感器。
参考链接:https://source.android.com/docs/devices/automotive/virtualization/architecture?hl=zh-cn
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。