本文首发于我的公众号 cloud_dev,专注于干货分享,号内有大量书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫。
上文「I/O 虚拟化」简单介绍了 I/O 虚拟化的做法,本文重点关注一下三种 I/O 虚拟化的分类——全虚拟化、半虚拟化和 I/O 直通(透传)。
I/O 全虚拟化
这种方式比较好理解,简单来说,就是通过纯软件的形式来模拟虚拟机的 I/O 请求。以 qemu-kvm 来举例,内核中的 kvm 模块负责截获 I/O 请求,然后通过事件通知告知给用户空间的设备模型 qemu,qemu 负责完成本次 I/O 请求的模拟。更具体的内容可以翻阅前文。
优点:
不需要对操作系统做修改,也不需要改驱动程序,因此这种方式对于多种虚拟化技术的「可移植性」和「兼容性」比较好。
缺点:
纯软件形式模拟,自然性能不高,另外,虚拟机发出的 I/O 请求需要虚拟机和 VMM 之间的多次交互,产生大量的上下文切换,造成巨大的开销。
I/O 半虚拟化
针对 I/O 全虚拟化纯软件模拟性能不高这一点,I/O 半虚拟化前进了一步。它提供了一种机制,使得 Guest 端与 Host 端可以建立连接,直接通信,摒弃了截获模拟这种方式,从而获得较高的性能。
值得注意的有两点:1)采用 I/O 环机制,使得 Guest 端和 Host 端可以共享内存,减少了虚拟机与 VMM 之间的交互;2)采用事件和回调的机制来实现 Guest 与 Host VMM 之间的通信。这样,在进行中断处理时,就可以直接采用事件和回调机制,无需进行上下文切换,减少了开销。
要实现这种方式, Guest 端和 Host 端需要采用类似于 C/S 的通信方式建立连接,这也就意味着要修改 Guest 和 Host 端操作系统内核相应的代码,使之满足这样的要求。为了描述方便,我们统称 Guest 端为前端,Host 端为后端。
前后端通常采用的实现方式是驱动的方式,即前后端分别构建通信的驱动模块,前端实现在内核的驱动程序中,后端实现在 qemu 中,然后前后端之间采用共享内存的方式传递数据。关于这方面一个比较好的开源实现是 virtio,后面会有专门的文章来讲述之。
优点:
性能较 I/O 全虚拟化有了较大的提升
缺点:
要修改操作系统内核以及驱动程序,因此会存在移植性和适用性方面的问题,导致其使用受限。
I/O 直通或透传技术
上面两种虚拟化方式,还是从软件层面上来实现,性能自然不会太高。最好的提高性能的方式还是从硬件上来解决。如果让虚拟机独占一个物理设备,像宿主机一样使用物理设备,那无疑性能是最好的。
I/O 直通技术就是提出来完成这样一件事的。它通过硬件的辅助可以让虚拟机直接访问物理设备,而不需要通过 VMM 或被 VMM 所截获。
由于多个虚拟机直接访问物理设备,会涉及到内存的访问,而内存又是共享的,那怎么来隔离各个虚拟机对内存的访问呢,这里就要用到一门技术——IOMMU,简单说,IOMMU 就是用来隔离虚拟机对内存资源访问的。
I/O 直通技术需要硬件支持才能完成,这方面首选是 Intel 的 VT-d 技术,它通过对芯片级的改造来达到这样的要求,这种方式固然对性能有着质的提升,不需要修改操作系统,移植性也好。
但该方式也是有一定限制的,这种方式仅限于物理资源丰富的机器,因为这种方式仅仅能满足一个设备分配给一个虚拟机,一旦一个设备被虚拟机占用了,其他虚拟机时无法使用该设备的。
为了解决这个问题,使一个物理设备能被更多的虚拟机所共享。学术界和工业界都对此作了大量的改进,PCI-SIG 发布了 SR-IOV (Single Root I/O Virtualizmion) 规范,其中详细阐述了硬件供应商在多个虚拟机中如何共享单个 I/O 设备硬件。
SR-IOV标准定义了设备原生共享所需的「软硬件支持」。硬件支持包括芯片组对 SR-IOV 设备的识别,为保证对设备的安全、隔离访问还需要北桥芯片的 VT-d 支持,为保证虚拟机有独立的内存空间,CPU 要支持 IOMMU。软件方面,VMM 将驱动管理权限交给 Guest,Guest 操作系统必须支持 SR-IOV 功能。
SR-IOV 单独引入了两种软件实体功能:
PF(physical function):包含轻量级的 PCIe 功能,负责管理 SR-IOV 设备的特殊驱动,其主要功能是为 Guest 提供设备访问功能和全局贡献资源配置的功能。
VF(virtual function):包含轻量级的 PCIe 功能。其功能包含三个方面:向虚拟机操作系统提供的接口;数据的发送、接收功能;与 PF 进行通信,完成全局相关操作。
每个 SR-IOV 设备都可有一个物理功能 PF,并且每个 PF 最多可有 64,000 个与其关联的虚拟功能 VF。
一般,Guest 通过物理功能 PF 驱动发现设备的 SR-IOV 功能后将包括发送、接收队列在内的物理资源依据 VF 数目划分成多个子集,然后 PF 驱动将这些资源子集抽象成 VF 设备,这样,VF 设备就可以通过某种通信机制分配给虚拟机了。
尽管 I/O 直通技术消除了虚拟机 I/O 中 VMM 干预引起的额外开销,但在 I/O 操作中 I/O 设备会产生大量的中断,出于安全等因素考虑,虚拟机无法直接处理中断,因此中断请求需要由 VMM 安全、隔离地路由至合适的虚拟机。所以,其实实际使用中,都是软硬件虚拟化方式结合使用的。
我的公众号 cloud_dev,号内有大量书籍和视频资源,后台回复「1024」即可领取,分享的内容包括但不限于云计算虚拟化、容器、OpenStack、K8S、雾计算、网络、工具、SDN、OVS、DPDK、Linux、Go、Python、C/C++编程技术等内容,欢迎大家关注。