转自:http://blog.csdn.net/wj_j2ee/article/details/7978259
目录
1 硬件虚拟化技术背景 2 KVM的内部实现概述
2.1 KVM的抽象对象
2.2 KVM的vcpu
2.3 KVM的IO虚拟化
2.3.1 IO的虚拟化
2.3.2 VirtIO 3 KVM-IO可能优化地方
3.1 Virt-IO的硬盘优化
3.2 普通设备的直接分配(Direct Assign)
3.3 普通设备的复用 =================================== 1 硬件虚拟化技术背景 硬件虚拟化技术通过虚拟化指令集、MMU(Memory Map Unit)以及IO来运行不加修改的操作系统。 传统的处理器通过选择不同的运行(Ring 特权)模式,来选择指令集的范围,内存的寻址方式,中断发生方式等操作。在原有的Ring特权等级的基础上,处理器的硬件虚拟化技术带来了一个新的运行模式:Guest模式[1],来实现指令集的虚拟化。当切换到Guest模式时,处理器提供了先前完整的特权等级,让Guest操作系统可以不加修改的运行在物理的处理器上。Guest与Host模式的处理器上下文完全由硬件进行保存与切换。此时,虚拟机监视器(Virtual Machine Monitor)通过一个位于内存的数据结构(Intel称为VMCS, AMD称为VMCB)来控制Guest系统同Host系统的交互,以完成整个平台的虚拟化。 传统的操作系统通过硬件MMU完成虚拟地址到物理地址的映射。在虚拟化环境中,Guest的虚拟地址需要更多一层的转换,才能放到地址总线上: Guest虚拟地址 -> Guest物理地址 -> Host物理地址
^ ^
| |
MMU1 MMU2 其中MMU1可以由软件模拟(Shadow paging中的vTLB)或者硬件实现(Intel EPT、AMD NPT)。MMU2由硬件提供。 系统的IO虚拟化技术,通常是VMM捕捉Guest的IO请求,通过软件模拟的传统设备将其请求传递给物理设备。一些新的支持虚拟化技术的设备,通过硬件技术(如Intel VT-d),可以将其直接分配给Guest操作系统,避免软件开销。 [1]X86处理器的生产厂商有自己的称谓,比如英特尔将Guest模式称为non-root operation,与之相对的是root operation,本文称为host模式。 2 KVM的内部实现概述 KVM是Linux内核的一个模块,基于硬件虚拟化技术实现VMM的功能。该模块的工作主要是通过操作与处理器共享的数据结构来实现指令集以及MMU的虚拟化,捕捉Guest的IO指令(包括Port IO和mmap IO)以及实现中断虚拟化。至于IO设备的软件模拟,是通过用户程序QEMU来实现的。QEMU负责解释IO指令流,并将其请求换成系统调用或者库函数传给Host操作系统,让Host上的驱动去完成真正的IO操作。她们之间的关系如下图所示: +--------------+ +--------+
| Qemu | | |
| | | |
| +---+ +----+| | Guest |
| |vHD| |vNIC||<-----+ | |
| +---+ +----+| | | |
+--------------+ | +--------+
^ | ^
| syscall |IO stream |
| via FDs | |
+----|----------------|------------|--------+
| | | v |
| v | +----------+ |
| +--------+ +------>| | |
| |drivers |<--+ | kvm.ko | |
| +--------+ | +----------+ |
| ^ | Host kernel |
+----|----------|---------------------------+
v v
+--------+ +---+
| HDD | |NIC|
+--------+ +---+
图 1 从Host操作系统的角度来看,KVM Guest操作系统相当于一个进程运行在系统上,普通的命令如kill、top、taskset等可以作用于该Guest。该进程的用户虚拟空间就是Guest的物理空间,该进程的线程对应着Guest的处理器。 从Qemu的角度来看,KVM模块抽象出了三个对象,她们分别代表KVM自己,Guest的虚拟空间以(VM)及运行虚拟处理器(VCPU)。这三个对象分别对应着三个文件描述符,Qemu通过文件描述符用系统调用IOCTL来操作这三个对象,同KVM交互。此时,Qemu主要只模拟设备,她以前的CPU和MMU的模拟逻辑都被kvm.ko取代了。 2.1 KVM的抽象对象 KVM同应用程序(Qemu)的交互接口为/dev/kvm,通过open以及ioctl系统调用可以获取并操作KVM抽象出来的三个对象,Guest的虚拟处理器(fd_vcpu[N]), Guest的地址空间(fd_vm), KVM本身(fd_kvm)。其中每一个Guest可以含有多个vcpu,每一个vcpu对应着Host系统上的一个线程。 Qemu启动Guest系统时,通过/dev/kvm获取fd_kvm和fd_vm,然后通过fd_vm将Guest的“物理空间”mmap到Qemu进程的虚拟空间,并根据配置信息创建vcpu[N]线程,返回fd_vcpu[N]。然后Qemu将操作fd_vcpu在其自己的进程空间mmap一块KVM的数据结构区域。该数据结构(下图中的shared)用于同kvm.ko交互,包含Guest的IO信息,如端口号,读写方向,内存地址等。Qemu通过这些信息,调用虚拟设备注册的回调函数来模拟设备的行为,并将Guest IO请求换成系统请求发送给Host系统。由于Guest的地址空间已经映射到Qemu的进程空间里面,Qemu的虚拟设备逻辑可以很方便的存取Guest地址空间里面的数据。三个对象之间的关系如下图所示: +----------+ | +--------+
| Qemu | Host user | | |
| | | | |
| | | | Guest |
| +------+| | | user |
| |shared|| | | |
| +------+| | | |
| ^ | | | |
+-------|--+ | | |
| | | | |
fds| | | | |
------|---|---------------| |--------|
| | | | |
v v Host kernel | | Guest |
+---------+ | | kernel |
| | | | |
| kvm.ko |----+ | | |
| | |fd_kvm | | |
+---------+ | | +--------+
v ^
+----+ fd_vm |
|vmcs|----+--------------
+------+ +----+ | +------+
| host | | | Guest|
| mode | |fd_vcpu | mode |
+------+ | +------+
^ v ^
| +-------+ |
| vm exit | Phy | vm entry|
+-------------| CPU |---------+
+-------+
图 2 图中vm-exit代表处理器进入host模式,执行kvm和Qemu的逻辑。vm-entry代表处理器进入Guest模式,执行整个Guest系统的逻辑。如图所示,Qemu通过三个文件描述符同kvm.ko交互,然后kvm.ko通过vmcs这个数据结构同处理器交互,最终达到控制Guest系统的效果。其中fd_kvm主要用于Qemu同KVM本身的交互,比如获取KVM的版本号,创建地址空间、vcpu等。fd_vcpu主要用于控制处理器的模式切换,设置进入Guest mode前的处理器状态等等(内存寻址模式,段寄存器、控制寄存器、指令指针等),同时Qemu需要通过fd_vcpu来mmap一块KVM的数据结构区域。fd_vm主要用于Qemu控制Guest的地址空间,向Guest注入虚拟中断等。 2.2 KVM的vcpu 如前文所述,KVM的vcpu对应着host系统上的一个线程。从Qemu的角度来看,她运行在一个loop中: for (;;) {
kvm_run(vcpu);
switch (shared_data->exit_reason) {
...
case KVM_IO:
handle_io(vcpu);
break;
case KVM_MMIO:
handle_mmio(vcpu);
break;
...
}
} 该线程同Guest的vcpu紧密相连。如果我们把线程的执行看作Guest vcpu的一部分,那么从Host的角度来看,该vcpu在三种不同的上下文中运行:Host user/Host kernel/Guest,将运行于一个更大的循环当中。该vcpu的运行逻辑如下图: Host user | Host kernel | Guest mode |
| | |
| | |
+->kvm_run(vcpu)-------+ | |
| | v | |
| | +->vm entry----------+ |
| | | | v |
| | | | Execute |
| | | | Natively |
| | | | | |
| | | vm exit<----------+ |
| | | | | |
| | | | | |
| Yes | | v | |
| +----------------I/O ? | |
| | | | | No | |
| | | | | | |
| | | | v | |
| v Yes | | Signal | |
+--Handle IO<---------Pending? | |
| | | No | |
| +----+ | |
图 3 实际上,在host上通过ps命令看到的关于vcpu这个线程的运行时间正是这三种上下文的总和。 2.3 KVM的IO虚拟化 2.3.1 IO的虚拟化 传统系统中,设备都直接或间接的挂在PCI总线上。PCI设备通过PCI配置空间以及设备地址空间接收操作系统的驱动请求和命令,通过中断机制通知反馈操作系统。配置空间和设备地址空间都将映射到处理器Port空间或者操作系统内存空间中,所以设备的软件模拟需要VMM将相关的Guest PIO和MMIO请求截获,通过硬件虚拟化提供的机制将其传送给软件。模拟软件处理完后再通过VMM提供的虚拟中断机制反馈Guest。如下图所示: +-----------------------------------+
| +--------------+ |
| | PCI config | +----------+ |
| +--------------+<--->| driver | |
| +--------------+<--->| | |
| | Device memory| +----------+ |
| +--------------+ ^ |
| ^ | |
+-------|--------------------|------+
| | vINTR via VMM
PIO/MMIO via VMM| +----------+
v |
+------------------------+
| +--------+ +--------+ |
| | PCI | | Device | |
| | config | | memory | | Virtual Device
| +--------+ +--------+ |
+------------------------+
|
v
+------------+
|host driver |
+------------+
图 4 虚拟设备的软件逻辑放在用户层也可以放在内核中。完全的虚拟设备模拟,可以处理在Guest中不加修改的驱动请求。通常这将消耗大量的处理器cycle去模拟设备。如果可以修改或者重写Guest的驱动代码,那么虚拟设备和驱动之间的IO接口可以根据虚拟化的特性重新定义为更高层更加高效的接口,如下图所示: +----------------+
| |
| +-----------+ |
| |para-driver| |
| +-----------+ |
+-------^--------+
|
| new I/O interface via VMM
v
+---------+
|Virtual |
|device |
+---------+
|
v
+------------+
|host driver |
+------------+
图 5 KVM的virtio正是通过这种方式提供了高速IO通道。 除了软件模拟,现有的硬件虚拟化技术还可以将一些支持虚拟化技术的新兴硬件直接分配给Guest。除了需要支持虚拟化技术的硬件(可以发起remmappable的MSI中断请求),设备的直接分配一般还需要主板上的芯片以及CPU支持,比如英特尔的VT-d技术。支持虚拟化技术的硬件平台主要做两件事,一个是DMA Remapping,将DMA请求中的Guest的物理地址映射到Host的物理地址,另一个是中断Remapping,将能remappable的中断请求根据由VMM设置,位于内存的IRT(Interrupt Remapping Table)发送到指定的vcpu上。 PC平台上,通常北桥(或者类似结构的root-complex)连接着CPU、内存以及外设。用于DMA Remapping和中断Remapping的硬件逻辑位于北桥中。如下所示: +-------------+
|cpu0, cpu1...|
+-------------+
^
| <-- System Bus
| |
v v
+---------------------+
| North Bridge |
| | +--------+
| +--------+ |<----->| Memory |
| | vt-d | | +--------+
| +--------+ |
+---------------------+
^ ^
| |
v v
+--------+ +--------+
| PCI-e | | South |<-----> PCI legacy devices...
| device | | Bridge |
+--------+ +--------+
图 6 目前,只有支持MSI的PCI/PCI-e设备才能直接分配给Guest。其中PCI-e设备可以直接与北桥相连或者桥连,然后单独分配给一个Guest。在一个桥后的所有的桥连PCI设备只能作为一个整体分配给一个Guest。KVM在硬件虚拟化的平台上支持PCI-e/PCI设备的直接分配。 2.3.2 VirtIO VirtIO为Guest和Qemu提供了高速的IO通道。Guest的磁盘和网络都是通过VirtIO来实现数据传输的。由于Guest的地址空间mmap到Qemu的进程空间中,VirtIO以共享内存的数据传输方式以及半虚拟化(para-virtualized)接口为Guest提供了高效的硬盘以及网络IO性能。其中,KVM为VirtIO设备与Guest的VirtIO驱动提供消息通知机制,如下图所示: +---------------+
| Qemu |
| +--------+ | +-------------------+
| | VirtIO | | | +---------+ |
| | Device | | | | VirtIO | Guest |
| +--------+ | | | Driver | |
+------|--^-----+ | +---------+ |
| | +---|---^-----------+
irqfd | | PIO | |
fd_vm | |ioeventfd | |vInterrupt
---------|--|------------------|---|------------
v | v |
+----------+ +--------------+ Host
| eventfd |<------->| KVM.ko | kernel
| core | | |
+----------+ +--------------+
图 7 如图所示,Guest VirtIO驱动通过访问port空间向Qemu的VirtIO设备发送IO发起消息。而设备通过读写irqfd或者IOCTL fd_vm通知Guest驱动IO完成情况。irqfd和ioeventfd是KVM为用户程序基于内核eventfd机制提供的通知机制,以实现异步的IO处理(这样发起IO请求的vcpu将不会阻塞)。之所以使用PIO而不是MMIO,是因为
KVM处理PIO的速度快于MMIO。 3 KVM-IO可能优化地方 3.1 Virt-IO的硬盘优化 从图1中可以看到,Guest的IO请求需要经过Qemu处理后通过系统调用才会转换成Host的IO请求发送给Host的驱动。虽然共享内存以及半虚拟化接口的通信协议减轻了IO虚拟化的开销,但是Qemu与内核之间的系统模式切换带来的开销是避免不了的。
目前Linux内核社区中的vhost就是将用户态的Virt-IO网络设备放在了内核中,避免系统模式切换以及简化算法逻辑最终达到IO减少延迟以及增大吞吐量的目的。如下图所示: +-------------------+
| +---------+ |
| | VirtIO | Guest |
| | Driver | |
| +-----+---+ |
+---|---^-----------+
PIO | |
| | vInterrupt
------------------------------|---|--------------
v |
+----------+ +--------------+ Host
| Vhost |<------->| KVM.ko | kernel
| net | | |
+----^-----+ +--------------+
|
|
+---v----+
| NIC |
| Driver |
+--------+
图 8 目前KVM的磁盘虚拟化还是在用户层通过Qemu模拟设备。我们可以通过vhost框架将磁盘的设备模拟放到内核中达到优化的效果。 3.2 普通设备的直接分配(Direct Assign) 如前文所述,目前只有特殊的PCI设备才能直接分配给相应的Guest,即VMM-bypass,避免额外的软件开销。我们可以在KVM中软实现DMA以及中断的remapping功能,然后将现有的普通设备直接分配给Guest。如下图所示: +----------------+
| Guest |
| +---------+ |
+-------->| | Driver | |
| | +---------+ |
| +------------^---+
D | | |
M | DMA Req.| | vINTR
A | | |
| +-------|-------|----------+
O | | v KVM | |
p | | +------------------+ |
e | | | DMA remmapping | |
r | | | | |
a | | | INTR remmapping | |
t | | +-----------^------+ |
i | +-------|-------|----------+
o | | | INTR
n | v |
| +---------+
+------------->| Deivce |
+---------+
图 9 这将大大减少Guest驱动同物理设备之间的路径(省去了KVM的涉入),去掉了虚拟设备的模拟逻辑,不过IO性能的提高是以增加KVM的逻辑复杂度的代价换来的。此时,IO的性能瓶颈从Qemu/KVM转移到物理设备,但是IO的稳定性、安全性将会更加依赖于KVM的remapping逻辑实现。 3.3 普通设备的复用 在普通设备的直接分配的基础上,我们甚至可以在多个Guest之间复用设备,好比m个进程跑在n个处理器上一样(n < m)。比如将一个硬盘分成多个区,每一个分区作为一个块设备直接分配给Guest;或者直接将n个网卡分配给m个Guest(n < m)。其中磁盘的复用,只需在KVM中添加分区管理的逻辑,而网卡的复用则要复杂一些:KVM需要为设备提供多个设备上下文(每一个设备上下文对应着一个Guest),同时还需要提供算法逻辑对设备上下文进行切换和调度。如下图所示: | KVM |
| Device context |
| queue |
+------+ | +-+ |
|Guest |---------->| | |
-------+ | +-+ |
| | |
+------+ | +-+ |
|Guest |---------->| | +----------+ |
+------+ | +-+ | Device | |
| | | Scheduler| |
+------+ | +-+ +----------+ |
|Guest |---------->| |-----+ |
+------+ | +-+ | |
| +--v--------+ |
| Current--->+--+ DM | | +-----+
| Context | +--+------------->| NIC |
| +-----------+ | +-----+
| | 图 10 其中,Device Modle(DM)实现前文提到的remapping逻辑,Device Scheduler用于选择和切换设备上下文实现物理设备的复用。在普通设备直接分配的基础上,通过对现有普通设备的复用,将会带来廉价、灵活、高效的IO性能。与之相对的是,目前已经有支持SR-IOV的网卡,从硬件上实现复用功能,支持多个(静态,即最大数目是内置的)虚拟的PCI网卡设备,价格昂贵,且受到一个网口总带宽有限的限制(软件复用技术,可以复用多个网卡,进而提高系统总的带宽)。 参考:
1[代码] qemu-kvm. git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git
2[代码] Linux-2.6{/virt/kvm/*, arch/x86/kvm/*, drivers/virtio/*, drivers/block/virtio_blk.c, drivers/vhost/*}
3[手册] Intel® Virtualization Technology for Directed I/O
4[手册] Intel® 64 and IA-32 Architectures Software Developer’s Manual 3B.
5[论文] Towards Virtual Passthrough I/O on Commodity Devices. 2008.
6[论文] kvm: the Linux Virtual Machine Monitor. 2007.
7[论文] virtio: Towards a De-Facto Standard For Virtual I/O Devices. 2008
8[论文] High Performance Network Virtualization with SR-IOV. 2010.
9[论文] QEMU, a Fast and Portable Dynamic Translator. 2005.

kvm qemu内幕介绍的更多相关文章

  1. KVM/QEMU桥接网络设置及kvm资料

    KVM/QEMU桥接网络设置 配置kvm的网络有2种方法.其一,默认方式为用户模式网络(Usermode Networking),数据包由NAT方式通过主机的接口进行传送.其二,使用桥接方式(Brid ...

  2. KVM+Qemu+Libvirt实战

    上一篇的文章是为了给这一篇文件提供理论的基础,在这篇文章中我将带大家一起来实现在linux中虚拟出ubuntu的server版来 我们需要用KVM+Qemu+Libvirt来进行kvm全虚拟化,创建虚 ...

  3. KVM+QEMU虚拟化概念

    概念: KVM,即Kernel-basedvirtual machine,由redhat开发,是一种开源.免费的虚拟化技术.对企业来说,是一种可选的虚拟化解决方案. 定义:基于Linux内核的虚拟机 ...

  4. 深入浅出 kvm qemu libvirt

    在所谓的kvm技术中,应用到的其实有2个东西:qemu+kvmkvm负责cpu虚拟化+内存虚拟化,实现了cpu和内存的虚拟化,但kvm不能模拟其他设备:qemu是模拟IO设备(网卡,磁盘),kvm加上 ...

  5. kvm/qemu虚拟机桥接网络创建与配置

    首先阐述一下kvm与qemu的关系,kvm是修改过的qemu,而且使用了硬件支持的仿真,仿真速度比QEMU快. 配置kvm/qemu的网络有两种方法.其一,默认方式为用户模式网络(Usermode N ...

  6. KVM/QEMU/qemu-kvm/libvirt 概念全解

    目录 目录 前言 KVM QEMU KVM 与 QEMU qemu-kvm Libvirt Libvirt 在 OpenStack 中的应用 前言 如果是刚开始接触虚拟机技术的话, 对上述的概念肯定会 ...

  7. gentoo在KVM+QEMU中安装笔记

    gentoo是比较难安装的,本笔记主要是记录本次安装过程,以备参考. 1.首先,下载镜像,可以去国内各大镜像网站下载,我选择的是清华的镜像源:https://mirrors.tuna.tsinghua ...

  8. KVM 介绍(5):libvirt 介绍 [ Libvrit for KVM/QEMU ]

    学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...

  9. QEMU,KVM及QEMU-KVM介绍

    What's QEMU QEMU是一个主机上的VMM(virtual machine monitor),通过动态二进制转换来模拟CPU,并提供一系列的硬件模型,使guest os认为自己和硬件直接打交 ...

随机推荐

  1. python-3高级特征

    1-切片 L = ["qinzb",'fengyong','bingyan'] L[0:3] #截取从索引0开始到索引3结束(不包含索引3) L[:3] #如果索引是从0开始则可省 ...

  2. Smail 中的一些点

    smali中所有操作都需要经过寄存器, 本地寄存器以v开头, 参数寄存器以p开头, 非static方法中p0是this 没有-object后缀的操作指令表示操作的对象是基本类型 invoke-dire ...

  3. saltstack特点

    目录 saltstack特点 saltstack特点 实时交互 所有的minion机器同时执行命令 no freeloader 每一台salt minion上都装有执行master传来的命令所需要的程 ...

  4. Pycharm的使用一

    一.编辑器的选择 Python 的学习过程少不了集成开发环境(IDE)或者代码编辑器,这些 Python 开发工具帮助开发者加快使用 Python 开发的速度,提高效率. 高效的代码编辑器或者 IDE ...

  5. Trident学习笔记(一)

    1. Trident入门 Trident ------------------- 三叉戟 storm高级抽象,支持有状态流处理: 好处是确保消费被处理一次: 以小批次方式处理输入流,得到精准一次性处理 ...

  6. curl 编译

    curl是利用URL语法在命令行方式下工作的开源文件传输工具.它被广泛应用在Unix.多种Linux发行版中,并且有DOS和Win32.Win64下的移植版本.支持很多协议:FTP, FTPS, HT ...

  7. 用Fragment实现如新浪微博一样的底部菜单的切换

    像我这个有强迫症的人来说,自从TabActivity抛弃之后,再使用看到一个个警告和一条条划着的横线,心里很不舒服,现在终于下定决心用Fragment来替换掉TabActivity了!我的研究成果如下 ...

  8. FTP被动模式服务器端开有限的端口

    很多服务器上都搭建的有FTP服务,FTP服务有两种连接模式:主动模式和被动模式.关于这两种模式的介绍,请参考这篇文章:重温FTP的主动模式和被动模式 关于这两种模式的比较,原文有这样的描述: 主动模式 ...

  9. markdown备忘

    文章主要(99%)参考自:markdown基本语法 这是二级标题 这是加粗的文字 这是倾斜的文字` 这是引用的内容 这是引用的内容 以下是分割线: 超链接 列表内容1 列表内容2 列表内容3 1.列表 ...

  10. (转\整)UE4游戏优化 多人大地型游戏的优化(四)内存的优化

    施主分享随缘,评论随心,@author:白袍小道,当苦无妨 小道暗语: 1.因为小道这里博客目录没自己整,暂时就用随笔目录结构,所以二级目录那啥就忽略了.标题格式大致都是(原or转) 二级目录 (标题 ...