1. 概述
Kvm是一种全虚拟化架构的虚拟机,其IO通常由qemu进行模拟实现,相比半虚拟化方案xen,其IO效率相对较低,为了提高kvm的IO效率,在其中引入virtio模块。Virtio是一种linux的半虚拟化IO框架,对块设备、网络等进行了虚拟化。将virtio运用半虚拟化思想,分为前端驱动和后端驱动,前端驱动在客户机中,因此,需要在原来客户机操作系统中增加一个新的virtio前端驱动模块,后端驱动处于主机中。前端驱动中,由虚拟队列中的环形缓冲区保存一次或多次IO请求,并交由后端驱动处理,最终由主机中设备驱动实现真正的IO操作,从而实现批量IO 处理,减少由于IO带来的vmexit/vmentry次数,提高虚拟机IO效率。将virtio引入kvm优点在于提高IO效率,而缺点在于需要对客户操作系统进行修改。
2. virtio前端驱动模块
Virtio分为前端与后端驱动,前端驱动在客户机操作系统中实现,在本文中,主要介绍前端驱动的架构以及与块设备相关的主要模块的初始化流程。
2.1 架构
前端驱动由多个模块组成,virtio作为一种linux 内部的API,连接块设备、网络设备等前端驱动模块,并通过连接点与后端驱动连接,如下图1:
由图可看出,前端驱动根据功能的不同,分为七个模块,分别包括块设备、网络设备、控制台等,其中与块设备虚拟化相关的模块包括:virito-pci、virtio、virtio-blk和Transport。
- virtio-pci:pci设备驱动,在pci总线扫描设备时,与设备进行匹配并驱动设备;
- virtio:虚拟总线,是pci的子系统,虚拟的块设备、网络设备均挂载在这个总线上;
- virtio-blk:虚拟块设备驱动程序,驱动挂载在virtio-bus上的虚拟设备;使用一个虚拟队列,与主机中的后端驱动进行通信;
- Tansport:环形缓冲区,即虚拟队列,这个缓冲区位于前端驱动与后端驱动之间,完成了客户机与主机之间的信息交互。
通过这四个模块的协同工作,完成了前端驱动中块设备的IO虚拟化。
2.2 模块初始化
Virtio前端中,块设备虚拟化主要由四个模块完成,这四个模块分别创建与初始化相关的数据结构,例如virtio初始化总线、virtio-pci初始化driver结构等,这些数据结构相互之间紧密联系,抽象化virtio前端驱动,如图2。本节从这个抽象化的结构出发,探讨virtio前端驱动模块初始化流程。
根据图2所示前端抽象层次,各个模块的初始化实际就是对这个模块中核心数据结构的初始化,接下来,假设系统启动后,在PCI总线上挂载一个能由virtio-blk驱动的设备,对virtio前端驱动模块初始化流程进行分析:
1)PCI扫描设备,发现可由virtio-pci驱动的设备,调用virtio_pci_init加载virtio-pci总线驱动,然后:
i. 调用pci_register_driver注册驱动,初始化pci_driver结构;
ii. 调用pci_bus_match匹配总线与pci_device设备,并调用pci_device_probe与virtio_pci_probe探测设备与驱动是否匹配,并填充virtio_pci_device结构;
iii. 调用register_virti