简介:virtio 是一种 I/O 半虚拟化解决方案,通过减少跨平台兼容性问题,提高驱动程序开发效率。本文将深入解析 virtio 的原理和架构。
VirtIO是一种I/O半虚拟化解决方案,它提供了一套通用的I/O设备虚拟化程序,对半虚拟化Hypervisor中的一组通用I/O设备进行抽象。VirtIO通过一组通用的模拟设备在虚拟机中变得可用,这些设备通过一个通用的应用编程接口(API)进行访问。
在完全虚拟化的解决方案中,guest VM要使用底层host资源,需要Hypervisor来截获所有的请求指令,然后模拟出这些指令的行为。这种做法势必会带来很多性能上的开销。而半虚拟化通过底层硬件辅助的方式,将部分没必要虚拟化的指令通过硬件来完成,Hypervisor只负责完成部分指令的虚拟化。要做到这点,需要guest来配合,guest完成不同设备的前端驱动程序,Hypervisor配合guest完成相应的后端驱动程序,这样两者之间通过某种交互机制就可以实现高效的虚拟化过程。
由于不同guest前端设备其工作逻辑大同小异(如块设备、网络设备、PCI设备、balloon驱动等),单独为每个设备定义一套接口实属没有必要,而且还要考虑跨平台的兼容性问题。另外,不同后端Hypervisor的实现方式也大同小异(如KVM、Xen等),这个时候,就需要一套通用框架和标准接口(协议)来完成两者之间的交互过程,VirtIO就是这样一套标准,它极大地解决了这些不通用的问题。
VirtIO的架构从总体上看可以分为四层:前端guest中各种驱动程序模块;后端Hypervisor(实现在Qemu上)上的处理程序模块;中间用于前后端通信的VirtIO层和VirtIO-ring层;以及VirtIO-ring层实现的两个环形缓冲区,分别用于保存前端驱动程序和后端处理程序执行的信息。严格来说,VirtIO和VirtIO-ring可以看做是一层,VirtIO-ring实现了VirtIO的具体通信机制和数据流程。或者这么理解可能更好,VirtIO层属于控制层,负责前后端之间的通知机制(kick、notify)和控制流程,而VirtIO-ring则负责具体数据流转发。
以virtio-blk磁盘为例,采用io_write函数将virtqueue的编号写到相应的寄存器,导致虚拟机退出,进行前端到后端的通知。采用中断注入方式实现后端到前端的通知,并通过IO环(vring)进行数据的共享。IO模型也随之发生变化。
总的来说,VirtIO是一种有效的I/O半虚拟化解决方案,通过提供一套通用的I/O设备虚拟化程序和标准接口(协议),解决了跨平台兼容性问题,提高了驱动程序开发效率。其架构包括前端驱动程序模块、后端处理程序模块、VirtIO层和VirtIO-ring层以及两个环形缓冲区。通过高效的通知机制和控制流程以及数据共享机制,VirtIO实现了高效的虚拟化过程。