虚拟化技术实现 — QEMU-KVM
目录
前文列表
KVM
KVM(Kernel-based Virtual Machine,基于内核的虚拟机)是一种用于 Linux 内核中的虚拟化基础设施。本质是一个嵌入到 Linux 内核中的虚拟化功能模块 kvm.ko(kvm-intel.ko/kvm-AMD.ko),该模块在利用 Linux 内核所提供的部分操作系统能力(e.g. 任务调度、内存管理、硬件设备交互)的基础上,再加入了处理器和内存虚拟化的能力,使得 Linux 内核具备了成为 VMM 的条件。KVM 于 2007 年 2 月 5 日被集成到 Linux 2.6.20 内核中。使用 KVM 的前提是宿主机必须拥有支持硬件虚拟化拓展特性(Intel VT 或者 AMD-V)的处理器。

KVM 的功能清单:
- 支持 CPU 和 Memory 超分(Overcommit)
- 支持半虚拟化 I/O(virtio)
- 支持热插拔 (CPU、块设备、网络设备等)
- 支持 SMP(Symmetric Multi-Processing,对称多处理)处理器架构
- 支持 NUMA (Non-Uniform Memory Access,非一致存储访问)处理器架构
- 支持实时迁移(Live Migration)
- 支持 PCI 设备直接分配(Pass-through)和单根 I/O 虚拟化 (SR-IOV)
- 支持合并相同内存页 (KSM )
以 Intel VT 为例,当启动 Linux 操作系统并加载 KVM 内核模块时:
- 初始化 KVM 模块内部的数据结构;
- KVM 模块检测当前的 CPU 体系结构,然后打开 CPU 控制器以及存取 CR4 寄存器的虚拟化模式开关,并通过执行 VMXON 指令将 Host OS/VMM(在 KVM 环境中,Host OS 即是 VMM)置于虚拟化模式的根模式(Root Mode);
- 最后,KVM 模块创建特殊的接口设备文件 /dev/kvm 并等待来自用户空间(QEMU)的指令。
但需要注意的是,KVM 是运行在内核态的且本身不能进行任何设备的模拟。所以,KVM 还必须借助于一个运行在用户态的应用程序来模拟出虚拟机所需要的虚拟设备(e.g. 网卡、显卡、存储控制器和硬盘)同时为用户提供操作入口。目前这个应用程序的最佳选择就是 QEMU。
QEMU
QEMU(Quick Emulator)是一款免费的、开源的、纯软件实现的、可执行硬件虚拟化的 VMM。与 Bochs,PearPC 等模拟器相比,QEMU 具有高速(配合 KVM)以及跨平台的特性。

事实上,QEMU 本身作为一套完整的 VMM 实现,包括了处理器虚拟化,内存虚拟化,以及模拟各类虚拟设备的功能。QEMU 4.0.0 版本甚至几乎可以模拟任何硬件设备,但由于这些模拟都是纯软件实现的,所以其性能低下。在 KVM 开发者在对 QEMU 进行稍加改造后,QEMU 可以通过 KVM 对外暴露的 /dev/kvm 接口来对其进行调用。从 QEMU 角度来看,也可以说是 QEMU 使用了 KVM 的处理器和内存虚拟化功能,为自己的虚拟机提供了硬件辅助虚拟化加速。除此以外,虚拟机的配置和创建、虚拟机运行所依赖的虚拟设备、虚拟机运行时的用户环境和用户交互,以及一些虚拟机的特定技术,比如:动态迁移,都是交由 QEMU 来实现的。

总的来说,QEMU 具有以下几种使用方式:
- 纯软件(二进制翻译)实现的全虚拟化虚拟机
- 基于硬件辅助虚拟化(KVM)的全虚拟化虚拟机
- 仿真器:为用户空间的进程提供 CPU 仿真,让在不同处理器结构体系上编译的程序得以跨平台运行。例如:让 SPARC 架构上编译的程序在 x86 架构上运行(借由 VMM 的形式)。
QEMU-KVM
KVM 官方提供的软件包下载包含了 KVM 内核模块、QEMU、qemu-kvm 以及 virtio 四个文件。其中,qemu-kvm 本质是专门针对 KVM 的 QEMU 分支代码包(一个特殊的 QEMU 版本)。
QEMU-KVM 相比原生 QEMU 的改动:
- 原生的 QEMU 通过指令翻译实现 CPU 的完全虚拟化,但是修改后的 QEMU-KVM 会调用 ICOTL 命令来调用 KVM 模块。
- 原生的 QEMU 是单线程实现,QEMU-KVM 是多线程实现。
然而在 QEMU 1.3 版本之后两者又保持一致了,但我们能仍习惯在 KVM 语境中将其称之为 QEMU-KVM。
NOTE:在 RHEL6/CentOS6 中,qemu-kvm 存放在 /usr/libexec 目录下。不过 PATH 环境变量缺省是不包含此目录的,所以用户无法直接使用 qemu-kvm,这样做是为了防止 QEMU 替代了 KVM 作为 VMM 的角色。如果希望启用 QEMU 作为 VMM 的话,可以通过将 /usr/libexec/qemu-kvm 链接为 /usr/bin/qemu 来完成。

在 QEMU-KVM 中,KVM 运行在内核空间,提供 CPU 和内存的虚级化,以及 Guest OS 的 I/O 拦截。QEMU 运行在用户空间,提供硬件 I/O 虚拟化,并通过 ioctl 调用 /dev/kvm 接口将 KVM 模块相关的 CPU 指令传递到内核中执行。当 Guest OS 的 I/O 被 KVM 拦截后,就会将 I/O 请求交由 QEMU 处理。例如:
open("/dev/kvm", O_RDWR|O_LARGEFILE) = 3
ioctl(3, KVM_GET_API_VERSION, 0) = 12
ioctl(3, KVM_CHECK_EXTENSION, 0x19) = 0
ioctl(3, KVM_CREATE_VM, 0) = 4
ioctl(3, KVM_CHECK_EXTENSION, 0x4) = 1
ioctl(3, KVM_CHECK_EXTENSION, 0x4) = 1
ioctl(4, KVM_SET_TSS_ADDR, 0xfffbd000) = 0
ioctl(3, KVM_CHECK_EXTENSION, 0x25) = 0
ioctl(3, KVM_CHECK_EXTENSION, 0xb) = 1
ioctl(4, KVM_CREATE_PIT, 0xb) = 0
ioctl(3, KVM_CHECK_EXTENSION, 0xf) = 2
ioctl(3, KVM_CHECK_EXTENSION, 0x3) = 1
ioctl(3, KVM_CHECK_EXTENSION, 0) = 1
ioctl(4, KVM_CREATE_IRQCHIP, 0) = 0
ioctl(3, KVM_CHECK_EXTENSION, 0x1a) = 0
QEMU-KVM 调用 KVM 内核模块启动虚拟机的流程概要
- 获取 /dev/kvm fd(文件描述符)
kvmfd = open("/dev/kvm", O_RDWR);
- 创建虚拟机,获取虚拟机的句柄。KVM_CREATE_VM 时,可以理解成 KVM 为虚拟机创建了对应的数据结构,然后,KVM 会返回一个文件句柄来代表该虚拟机。针对这个句柄执行 ioctl 调用即可完成对虚拟机执行相应的管理,比如:创建用户空间虚拟地址(Virtual Address)、客户机物理地址(Guest Physical Address)以及主机物理地址(Host Physical Address)之间的映射关系;
vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
- 为虚拟机映射内存和其他的 PCI 设备,以及信号处理的初始化。
ioctl(kvmfd, KVM_SET_USER_MEMORY_REGION, &mem);
将虚拟机镜像数据映射到内存,相当于物理机的 boot 过程,把操作系统内核映射到内存。
创建 vCPU,并为 vCPU 分配内存空间。KVM_CREATE_VCPU 时,KVM 为每一个 vCPU 生成对应的文件句柄,对其执行相应的 ioctl 调用,就可以对 vCPU 进行管理。
ioctl(kvmfd, KVM_CREATE_VCPU, vcpuid);
vcpu->kvm_run_mmap_size = ioctl(kvm->dev_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
- 创建 vCPU 个数的线程并运行虚拟机。
ioctl(kvm->vcpus->vcpu_fd, KVM_RUN, 0);
- 线程进入循环,监听并捕获虚拟机退出原因,做相应的处理。这里的退出并不一定指的是虚拟机关机,虚拟机如果遇到 I/O 操作,访问硬件设备,缺页中断等都会执行退出。执行退出可以理解为将 CPU 执行上下文返回到 QEMU。
open("/dev/kvm")
ioctl(KVM_CREATE_VM)
ioctl(KVM_CREATE_VCPU)
for (;;) {
ioctl(KVM_RUN)
switch (exit_reason) { /* 分析退出原因,并执行相应操作 */
case KVM_EXIT_IO: /* ... */
case KVM_EXIT_HLT: /* ... */
}
}
虚拟化技术实现 — QEMU-KVM的更多相关文章
- 主流服务器虚拟化技术简单使用——KVM(二)
通过Linux工具管理KVM 主流服务器虚拟化技术简单使用——KVM(一)部署了一台KVM主机,提到KVM可以通过命令行工具(virt-install.virsh)和GUI工具(virt-manage ...
- 虚拟化技术xen,kvm,qemu区别
虚拟化类型 全虚拟化(Full Virtualization) 全虚拟化也成为原始虚拟化技术,该模型使用虚拟机协调guest操作系统和原始硬件,VMM在guest操作系统和裸硬件之间用于工作协调,一些 ...
- 主流服务器虚拟化技术简单使用——KVM(一)
Tips:因为博客园排版的原因,图片显示不清晰,可以放大网页查看清晰图片. 如果系统使用物理机,需要在BIOS里面开启Intel VT-x(或AMD-V),如果是VMware workstation, ...
- Linux虚拟化技术KVM、QEMU与libvirt的关系(转)
说明:个人理解,KVM是内核虚拟化技术,而内核是不能使用在界面上使用的,那么此时QEMU提供了用户级别的使用界面,相互辅助.当然,单独使用QEMU也是可以实现一整套虚拟机,不过QEMU+KVM基本是标 ...
- 云计算大数据:Xen、KVM、VMware、hyper-v等虚拟化技术的比较
1.Xen.KVM.VMware.hyper-v等虚拟化技术的比较,xen和kvm,是开源免费的虚拟化软件. vmware是付费的虚拟化软件. hyper-v比较特别,是微软windows 2008 ...
- 虚拟化技术对比:Xen vs KVM
恒天云:http://www.hengtianyun.com/download-show-id-68.html 一.说明 本文主要从功能方面和性能方面对Xen和KVM对比分析,分析出其优缺点指导我们恒 ...
- 虚拟化技术:Xen与KVM的对比
作为开源的虚拟化技术,对比Xen和KVM可以看到,Xen以6个无与伦比的优势领先:更好的可用资源.平台支持.可管理性.实施.动态迁移和性能基准. 可用资源:Xen的问世要比KVM早4年之久(两者分别是 ...
- 虚拟化技术对照:Xen vs KVM
恒天云:http://www.hengtianyun.com/download-show-id-68.html 一.说明 本文主要从功能方面和性能方面对Xen和KVM对照分析,分析出其优缺点指导我们恒 ...
- kvm/qemu/libvirt学习笔记 (1) qemu/kvm/libvirt介绍及虚拟化环境的安装
kvm简介 kvm最初由Quramnet公司开发,2008年被RedHat公司收购.kvm全称基于内核的虚拟机(Kernel-based Virtual Machine),它是Linux的一个内核模块 ...
- KVM虚拟化技术(七)虚拟机配置文件
KVM虚拟机的配置文件在/etc/libvirt/qemu/下,为xml文件 整体结构如下: <domain type='kvm'> 虚拟机整体信息 系统信息 硬件资源特性 突发事件处理 ...
随机推荐
- 【Flask+Redis】 python学习第一章 - 7.0 断言 数据库测试 redis学习
assert 断言 def div(num1, num2): # 断言 assert isinstance(num1, int), "值类型错误" assert isinstanc ...
- SVN将项目代码加入svn版本控制
将已有项目代码加入svn版本控制 - TortoiseSVN入门篇Windows下SVN实用教程(以TortoiseSVN作为客户端(client)) 翻译: Bravo Young Next: 版本 ...
- 【转】PS1应用-修改linux终端命令行字体颜色
原文链接:https://www.jianshu.com/p/4239d3ea72fe cd ls -la vim .bashrc 在.bashrc中加入这一行: PS1="\[\e[37; ...
- Array 和 ArrayList 有何区别?(未完成)
Array 和 ArrayList 有何区别?(未完成)
- 导弹拦截( 二分+dilworth定理)
https://www.luogu.org/problemnew/show/P1020 原题 接下来是dilworth定理 https://blog.csdn.net/u011676717/artic ...
- JavaScript005,语法
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- 能用的单纯形法python代码
网上找了一些代码,发现有一些是不能用的,出现错误说集合为空 1.网上出现了好多次,但是不能用的,只能部分模型能用,比如例子中所示 原链接:https://www.jianshu.com/p/b233c ...
- Nginx服务器的Websockets配置方法
这篇文章主要介绍了简介Nginx服务器的Websockets配置方法,是使用Nginx服务器的网管的必备知识XD~需要的朋友可以参考下 Nginx 1.3.13 已经发布了,该版本支持 Connect ...
- 二分法:从一个只包含数字的list中查找某个数
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2017/4/10 19:03 # @Author : MnCu # @Site : # ...
- <input type="file"> accept属性筛选文件类型
如果你不希望用户上传任何类型的文件, 你可以使用 input 的 accept 属性. 设置支持 .doc / .docx / .xls / .xlsx / .pdf 格式: <input ty ...