共计 5374 个字符,预计需要花费 14 分钟才能阅读完成。
1 I/O虚拟化
前面我们已经讲过CPU的虚拟化技术,而I/O虚拟化,也是虚拟化技术中之分重要的一部分。虚拟化包含CPU、内存、I/O设备(网络属于特殊的IO设备)的虚拟化。前面我们也提到了,I/O设备虚拟化也分为全虚拟化、半虚拟化以及硬件辅助的虚拟化。
2 知识回顾
虚拟化分类早期有两种模型host模型和hypervisor模型,这两种模型的划分其实是来自于早期VMware的ESX和GSX。
上述两种虚拟技术类型,其中 Type1 的HyperVisor独立于硬件之上,但是个人理解,HyperVisor不可能脱离OS(Operating System)去独立地进行硬件的操作,Type1中的HyperVisor也包含了一个最简单的OS内核,无非就是这个内核上不能跑其他的应用罢了。因此可以将Type1的HyperVisor理解为 Mini OS+VMM(Virtual Machine Manager),而Type2的HyperVisor可以理解为单独的VMM。但是目前主流的HyperVisor产品之一KVM的出现已经打破了这种简单的划分方式,对虚拟化技术还未有更精确的分类方式出现。
3 I/O虚拟化分类
在详细介绍各个分类之前,我们先考虑一下,在没有虚拟化技术之前,操作系统是怎么对I/O请求进行处理的。当某个应用或者进程发出I/O请求,会通过系统调用的方式进入内核,调用相应的设备驱动程序,请求到具体的I/O设备,最后再将结果返回给进程。
那么存在虚拟机的情况,又怎么让每个虚拟机都有自己的一套宿主机上的I/O设备呢?
常见的I/O虚拟化实现方案分为以下三类:
分别是整体模型、服务VM模型、直通模型。
第一种情况是整体模型,它将I/O服务和设备驱动都直接装载在HyperVisor的Mini OS上,所有VM的I/O请求都会被VMM捕获,然后通过软件模拟的方式,将结果返回给Guest OS。图中说这种方式拥有较高的性能,据我个人理解,应该是和第二种模型进行比较,因为该种方式是因为所有的I/O请求都必须通过VMM层软件进行模拟,上下切换频繁,性能并不一定高。 但是确定却很明显,Hypervisor会很大,代表产品就是VMWare的ESX和ESXi,另一个缺点就是对新设备的驱动加载不够方便,有时需要升级整个Hypervisor,比如ESXi直到5.0版本才能识别出Qlogic驱动的CNA网卡。如果采用这种方案,一定要先确认好Hypervisor的支持驱动列表再进行安装。
第二种服务VM模型,从图中可以看到,它通过加载一个服务系统(如Domain 0)来减少Hypervisor的负担,所有的产品驱动都安装在服务系统上,这样便于其他外设硬件的管理和增加,同时减小了Hypervisor,越小意味着越安全,降低了故障的风险。缺点是性能相较于第一种,性能不好,因为所有的服务调用都要经过服务系统。典型代表就是Xen和Hyper-V。KVM有些类似,但是不完全一样,因为KVM的Hypervisor和服务系统使用同一个Linux内核,而Xen和Hyper-V使用的各自精简的内核,与服务系统不同,之后会介绍。
提到这里有必要讲一下有些公开资料上提到的I/O 全虚拟化、半虚拟化了,我参考的这篇文章作者提到上述两种模型又被称为I/O Full-virtualization(全虚拟化)和I/O Para-Virtualization(半虚拟化),但是与此同时,我在网上公开中找到的I/O全虚拟化、半虚拟化技术的解释完全不同,他们都说I/O全虚拟化技术性能不高,半虚拟化技术性能相较于全虚拟化技术有所提高。由于没找到上述图片的出处,倒是在中兴公司的云计算技术PPt中找到了上述三个模型的分类,在IBM的开发社区中也找了类似的说法,到那时IBM中描述的是设备仿真架构,一个是基于Hypervisor的设备仿真(对应于第一种整体模型),一个是用户空间的设备仿真(对应第二种服务VM模型),他们都说的是第二种比第一种安全性稿、性能差,并不像《从半空看虚拟化》文章中提到的,上述两种可以被称之为全虚拟化和半虚拟化。这点我们先留个疑问,后续章节详细介绍一下,这两种分类的区别。
第三种直通模型则是从硬件层面已经将各个设备进行了划分,分配给不同的VM使用,由每个VM自行维护其使用的IO和设备驱动。Hypervisor只提供通道,不再对I/O和设备驱动进行管理。这样做的好处是可以达到最高的性能和最小的代码量(Hypervisor),但缺点是设备非完全共享且对VM迁移提出了一定挑战。这种方案只有在对I/O操作要求较高的特定场景下使用,不具备普适性。部署时I/O设备支持逻辑划分技术如SR IOV( Single RootI/o virtualization)等即可,对 Hypervisor没有什么特殊要求,前面说的几款主流产品都提供了此种工作方式。
Intel的VT-d技术作为一种平台结构在硬件层面可以有效的对上面三种方案全部提供支持。其根本目的就是为了多个VM在对虚拟设备进行I/O操作时,能够对其DMA和中断处理进行隔离保护与提升性能。
4 另一种分类方式
在网上可以查到的公开资料中,大家又将I/O虚拟化分为全虚拟化、半虚拟化、I/O直通或透传技术三种。这三种技术,最终经过查证,我认为上节中的前两种模型和全虚拟化、半虚拟化联系并不大,全虚拟化、半虚拟化区分角度应该是是否需要修改Guest OS。因为全虚拟化、半虚拟化都是通过软件的方式来进行模拟。下面我们简单介绍一下,这种分类方式。
4.1 I/O 全虚拟化
全虚拟化即不修改Guest OS,通过VMM来实现模拟IO设备。全虚拟化,既可以是上节中的第一种模型,也可以是第二种模型。全虚拟化和半虚拟化可以通过观察是否修改了Guest OS来划分。
在全虚拟化情况下,Guest OS所能看到的就是一组统一的I/O设备。下面我们以KVM和Xen的两种IO全虚拟化模型为例介绍全虚拟化,相信大家可以找到I/O全虚拟化的共同点。
4.1.1 KVM-QEMU
下面以KVM的全虚拟化I/O为例 ,KVM 在 IO 虚拟化方面,传统或者默认的方式是使用 QEMU 纯软件的方式来模拟 I/O 设备,包括键盘、鼠标、显示器,硬盘 和 网卡 等。模拟设备可能会使用物理的设备,或者使用纯软件来模拟。模拟设备只存在于软件中。
过程:
- 客户机的设备驱动程序发起 I/O 请求操作请求
- KVM 模块中的 I/O 操作捕获代码拦截这次 I/O 请求
- 经过处理后将本次 I/O 请求的信息放到 I/O 共享页 (sharing page),并通知用户空间的 QEMU 程序。
- QEMU 程序获得 I/O 操作的具体信息之后,交由硬件模拟代码来模拟出本次 I/O 操作。
- 完成之后,QEMU 将结果放回 I/O 共享页,并通知 KMV 模块中的 I/O 操作捕获代码。
- KVM 模块的捕获代码读取 I/O 共享页中的操作结果,并把结果放回客户机。
注意:当客户机通过DMA (Direct Memory Access)访问大块I/O时,QEMU 模拟程序将不会把结果放进共享页中,而是通过内存映射的方式将结果直接写到客户机的内存中共,然后通知KVM模块告诉客户机DMA操作已经完成。
4.1.2 Xen
我们再看一下基于I/O全虚拟化的Xen的模型:
当虚拟机访问虚拟设备时,访问请求被虚拟机监视器截获,然后监视器程序将 I/O 请求交由 domain 0 来模拟完成,最后将结果返回给虚拟机 。
4.1.3 I/O 全虚拟化总结
可以看出,不论是KVM还是Xen的IO全虚拟化实现,都是修改Hypervisor层的东西,并没有修改Guest OS,都是通过软件模拟设备的方式,因此可移植性与兼容性很好,这也是它被广泛使用的主要原因。但是 I/O 全虚拟化有一个很大的不足之处,就是性能较差,主要原因有两方面:
- 第一、模拟方式是用软件行为进行模拟,这种方式本身就无法得到很高的性能;
- 第二、这种模型下 I/O 请求的完成需要虚拟机与监视器程序多次的交互,产生大量的上下文切换,造成巨大开销。
讲了那么多,可以发现,全虚拟化与第三节中提到的整体模型和服务VM模型都有重合的点。
4.2 I/O 半虚拟化
众多公开资料中都显示,I/O半虚拟化是采用前后端驱动的方式来实现,相较于全虚拟化,半虚拟化提高了性能。而其原因为:
- 采用 I/O 环机制,使得 Guest 端和 Host 端可以共享内存,减少了虚拟机与 VMM 之间的交互;
- 采用事件和回调的机制来实现 Guest 与 Host VMM 之间的通信。这样,在进行中断处理时,就可以直接采用事件和回调机制,无需进行上下文切换,减少了开销。
下面,我们同样也以KVM和Xen两种实现的不同I/O半虚拟化作为例子来介绍。
4.2.1 KVM-QEMU
先以KVM为例,针对 I/O 全虚拟化纯软件模拟性能不高这一点,I/O 半虚拟化前进了一步。它提供了一种机制,使得 Guest 端与 Host 端可以建立连接,直接通信,摒弃了VMM截获模拟这种方式,从而获得较高的性能。
这种方式类似C/S通信的方式,在Guest中添加前端驱动,Host的Qemu中添加后端驱动,前后端通过通向内存的方式传递数据。KVM使用的就是Virtio这个Linux上的设备驱动标准框架来实现。这里提一下,KVM/QEMU 的 virtio 实现采用在 Guest OS 内核中安装前端驱动 (Front-end driver)和在 QEMU 中实现后端驱动(Back-end)的方式。前后端驱动通过 vring 直接通信,这就绕过了经过 KVM 内核模块的过程,达到提高 I/O 性能的目的。
显然这种方式需要修改Guest OS内核,因此是半虚拟化。
4.2.2 Xen
下图是Xen的IO半虚拟化模型,可以看到和KVM的基本类似,只是Xen的Domain 0 是作为服务系统,其前后端驱动通过共享内存等方式,优化了性能。
4.2.3 I/O半虚拟化总结
通过上述描述,可以看出半虚拟化方式,相较于全虚拟化方式提升了性能,这跟第三节中的前两种模型也是互有交叉,不能把半虚拟化等同于服务VM模型、全虚拟化等同与整体模型,因为半虚拟化性能相较于全虚拟化性能提升,而整体模型性能优于服务VM模型。
对于I/O半虚拟化,性能提升是其主要的有点,但是由于它要修改操作系统内核以及驱动程序,因此会存在移植性和适用性方面的问题,导致其使用受限。
4.3 I/O直通或透传技术
也有的称为硬件辅助虚拟化。
上面两种虚拟化方式,还是从软件层面上来实现,性能自然不会太高。最好的提高性能的方式还是从硬件上来解决。如果让虚拟机独占一个物理设备,像宿主机一样使用物理设备,那无疑性能是最好的。I/O 直通技术就是提出来完成这样一件事的。它通过硬件的辅助可以让虚拟机直接访问物理设备,而不需要通过 VMM 或被 VMM 所截获。
X86主要设备厂商Intel和 AMD 都在其较新的处理器架构中提供对I/O直通的支持(除了辅助虚拟机管理程序的新指令之外)。Intel 将其称为Technology for Directed I/O (VT-d) , 而 AMD 则将其称为 I/O Memory Management Unit(IOMMU)。不论是哪一种,新的 CPU 都提供了将 PCI 物理地址映射到Guest 虚拟地址的方法。发生此映射时,硬件负责访问(和保护),并且客户机操作系统可以使用设备,就好像它是非虚拟化系统一样。除了将Guest映射到物理内存之外,还提供了隔离,以便阻止其他Guest(或虚拟机管理程序)访问它。
在IBM开发者中心提到,有一种技术叫做Message Signaled Interrupts (MSI),可以用于中断大量虚拟机,将中断更容易虚拟化,并且允许隔离中断源,IBM甚至称这是I/O虚拟化的理想选择,感兴趣的同学可以在文末参考文献中找到。
可以看到I/O直通技术可以让当虚拟机独占物理设备,这样虽然性能提升了,但是一个设备只能被一个虚拟器使用,降低了设备使用率。为了实现一个物理设备能被多个虚拟机共享,学术界和工业界都为此作了大量的改进,于是PCI-SIG 发布了 SR-IOV (Single Root I/O Virtualizmion) 规范,其中详细阐述了硬件供应商在多个虚拟机中如何共享单个 I/O 设备硬件。这里也不详细介绍SR-IOV了,有机会再去深究。
参考文献
- 《从半空看虚拟化》
- I/O 虚拟化的三种形式 – 简书 (jianshu.com)
- Linux云计算底层技术之 I/O 虚拟化的三种形式 – 知乎 (zhihu.com)
- 虚拟化技术. – ppt download (slidesplayer.com)
- Linux virtualization and PCI passthrough – IBM Developer
- 浅谈网络I/O全虚拟化、半虚拟化和I/O透传 – 简书 (jianshu.com)
- KVM 介绍(3):I/O 全虚拟化和准虚拟化 – dion至君 – 博客园 (cnblogs.com)
- (49条消息) IO虚拟化及虚拟化模型_暗夜公爵LKN的博客-CSDN博客_io虚拟化
- 胡冷非, 李小勇. 基于 Xen 的 I/O 准虚拟化驱动研究[J]. 计算机工程, 2009, 35(23): 258-259.
- Linux 下检查 VT-d / IOMMU 是否开启 – 知乎 (zhihu.com)
- 虚拟化技术之虚拟化技术介绍及Xen的应用实现_Opensamlee的技术博客_51CTO博客