转自:http://blog.csdn.net/julykobe/article/details/27571387

注:本文内容均来自网络,我只是在此做了一些摘抄和整理的工作,来源均有注明。

0、虚拟化

虚拟化简介

我们首先简要介绍一下虚拟化,阐述 QEMU 的搭建背景。

本文中介绍的虚拟化实际上指的是平台虚拟化。在物理硬件上,控制程序可能是主机操作系统或管理程序(见图 1)。在某些情况下,主机操作系统就是管理程序。来宾操作系统位于管理程序中。在某些情况下,来宾操作系统与控制程序使用相同的 CPU,而在另外一些情况下,则可能不同(比如 PowerPC
来宾操作系统在 x86 硬件上运行)。

图 1. 平台虚拟化的基本架构

您可以通过多种方法实现虚拟化,但是最常见的有三种。第一种称为本地虚拟化(或全虚拟化)。在这种虚拟化中,管理程序实现基本的隔离元素,将物理硬件与来宾操作系统相分离。这种技术首次出现于 1966 年 IBM® CP-40 虚拟机/虚拟内存操作系统中,另外 VMware ESX Server
也使用了此技术。

另一种流行的虚拟化技术称为半虚拟化。在半虚拟化中,控制程序实现了管理程序的应用程序接口(API),它将由来宾操作系统使用。Xen 和 Linux Kernel-based Virtual Machine (KVM) 都使用了半虚拟化技术。

第三种有用的技术称为仿真。仿真,顾名思义,通过模拟完整的硬件环境来虚拟化来宾平台。仿真可通过多种方法实现,即使在同一个解决方案中也是如此。通过仿真实现虚拟化的技术有 QEMU 和 Bochs。


 

1、KVM

概念:

KVM是Kernel-based Virtual Machine的缩写。从Linux kernel 2.6.20开始就包含在Linux内核代码之中,使用这个或者更高版本内核的Linux发行版,就直接可以使用KVM。KVM依赖于host
CPU的虚拟化功能的支持(Intel-VT & AMD-V),类似于Xen的HVM,对于guest OS的内核没有任何的要求,可以直接支持创建Linux和Windows的虚拟机。

     下图解释了KVM的运行原理:
     KVM支持用户态(Userspace)进程通过KVM内核(Kernel)模块利用CPU的虚拟化技术创建虚拟机。虚拟机的vCPU映射到进程中的线程,虚拟机的RAM映射到进程的内存地址空间,IO和外围设备通过进程进行虚拟化,也就是通过QEMU。所以我们看到在OpenStack中创建一个虚拟机就对应一个计算节点的QEMU进程。
 
     刚才说到guest OS
RAM的地址空间映射到qemu-kvm进程的内存地址空间,这样进程就可以很容易的对于guest
OS的RAM进行控制,当guest需要使用RAM时,qemu-kvm就在自己的进程内存空间中划分一段给guest用。对于guest
OS设置了MaxMemory和CurrentMemory之后,guest
OS的RAM上限也就有了,就是MaxMemory,如果当前的guest实际使用不了那么多RAM,就可以将CurrentMemory调小,将多余的内存还给host,guest中看到的内存大小就是CurrentMemory,这就是Memory
Balloon特性。
 
架构:
     KVM由两部分组成,一部分称为KVM Driver。已经成为Linux内核的一个模块,负责虚拟机的创建、虚拟机内存的分配、虚拟CPU寄存器的读写以及虚拟CPU的运行等;另一部分是稍微修过的Qemu,用于模拟PC硬件的用户空间组件、提供I/O设备模型以及访问外设的途径。
     
     图1揭示了KVM的基本结构(Libkvm是KvM提供给Qemu的应用程序接口)。KVM Driver加入到标准的Linux内核中,被组织成Linux中的标准字符设备(/dev/kvm),用户模式的Qemu可以通过一系列的ioctl系统调用访问这个字符设备从而创建和运行虚拟机。KVMDriver的加入使得整个Linux内核成为一个虚拟机监控器(Virtual
Machine Monitor),并且在原有Linux操作系统两种执行模式(用户模式和内核模式)的基础上,增加了一种客户模式(拥有自己的内核模式和用户模式),这三种模式不同的分工分别是:
客户模式:执行非I/0的客户代码。虚拟机就运行在客户模式下。
内核模式:实现到客户模式的切换,处理由于I/O或其他指令引起的从客户模式的退出。KVM Driver工作在这种模式下。
用户模式:代表客户执行I/0指令。Qemu运行在这种模式下。
我们把运行于虚拟机内的操作系统称为Guest
OS,把底层的Linux操作系统称为Host OS。在KVM模型中,每一个Guest
OS对Linux来说是一个标准的进程,可以使用Linux的进程管理指令管理,例如用taskset指定运行于某个特定的CPU,也可以用kill终止虚拟机的运行。
 
    
 
     从图2中我们可以清楚的看到KVM的基本工作原理。首先在用户模式的Qemu通过ioctl系统调用,进入内核模式。KVM Driver为虚拟机创建虚拟内存和虚拟CPU之后执行VMI.AUNCH指令进入客户模式,装载GuestOS,而后执行客户代码。如果Guest
OS发生外部中断或者影子页表缺页之类的事件,暂停Guest OS的运行,退出客户模式进入内核做一些必要的处理,而后重新进入客户模式。继续执行客户代码;如果发生I/0事件或者信号队列中有信号到达,就会进入用户模式处理。
     KVM采用全虚拟化技术(可以通过给当前内核打kvm-paravirt-patches补丁来支持半虚拟化),Guest OS不需要修改就可以直接在在其上运行,弥补了半虚拟化技术的不足。
 

 

2、QEMU

概念:
 
 
 刚才讲KVM的时候一直说进程可以通过KVM模块创建虚拟机,那个所谓的进程其实就是QEMU。KVM团队维护了一个QEMU的分支版本(qemu-kvm),使QEMU可以利用KVM在x86架构上加速,提供更好的性能。qeum-kvm版本的目标是将所有的特性都合入上游的QEMU版本,之后这个版本会废弃,直接使用QEMU主干版本。
     其实,之前还有Xen维护的QEMU版本,叫做qemu-xen,由于所有的特性都已经合入QEMU1.0,所以Xen现在直接使用了QEMU。
     #"之前在安装OpenStack的时候,都需要安装一个包kvm,我个人认为这个包其实就是QEMU,KVM是已经包含在Linux Kernel里了,所以不需要再安装。包名称使用kvm有点混淆概念。这点在Ubuntu的包描述上可以看出来。"
     在Nova的配置文件中有一个virt_type配置项,可以配置成kvm也可以是qemu,这里的kvm其实指的也是qemu-kvm。如果要配置成kvm,需要host的CPU支持Intel-VT和AMD-V技术,并且要载入kvm内核模块,由于有硬件加速,创建的guest

OS的性能要优于qemu;qemu配置项指的就是完全的QEMU虚拟化,没有硬件加速,主要用于比较老式的CPU和操作系统环境,或者是在虚拟机中创建虚拟机的情况,当然完全的QEMU虚拟化性能要比qemu-kvm差一些

     QEMU的功能大致分为两类:
  • 模拟(emulator)
  • 虚拟化(virtualizer)

模拟:就是在一种CPU架构上模拟另一种CPU架构,运行程序。例如:在x86环境上模拟ARM的运行环境,执行ARM程序,或者在PowerPC环境上模拟x86指令集。
     虚拟化:就是在host OS上运行guest OS的指令,并为guest OS提供虚拟的CPU、RAM、IO和外围设备。

     我们在OpenStack中使用的就是QEMU的虚拟化功能。
     QEMU进程直接使用了KVM的接口/dev/kvm,向KVM发送创建虚拟机和运行虚拟机的命令。框架代码如下:
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: /* ... */
}
}
     虚拟机运行起来之后,当guest OS发出硬件中断或者其它的特殊操作时,KVM退出,QEMU可以继续执行,这时QEMU根据KVM的退出类型进行模拟IO操作响应guest OS。
     由于QEMU是一个普通的用户态进程,而guest OS的运行又在QEMU当中,所以host不能绕过QEMU直接观察guest OS。但是QEMU提供了一系列的接口可以导出guest OS的运行情况,内存状态和IO状态等。
     以下就是一个QEMU进程:
109       1673     1  1 May04 ?        00:26:24 /usr/bin/qemu-system-x86_64 -name instance-00000002 -S -machine pc-i440fx-trusty,accel=tcg,usb=off -m 2048 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid f3fdf038-ffad-4d66-a1a9-4cd2b83021c8 -smbios type=1,manufacturer=OpenStack Foundation,product=OpenStack Nova,version=2014.2,serial=564d2353-c165-6238-8f82-bfdb977e31fe,uuid=f3fdf038-ffad-4d66-a1a9-4cd2b83021c8 -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/instance-00000002.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -boot strict=on -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/opt/stack/data/nova/instances/f3fdf038-ffad-4d66-a1a9-4cd2b83021c8/disk,if=none,id=drive-virtio-disk0,format=qcow2,cache=none -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1 -drive file=/opt/stack/data/nova/instances/f3fdf038-ffad-4d66-a1a9-4cd2b83021c8/disk.config,if=none,id=drive-ide0-1-1,readonly=on,format=raw,cache=none -device ide-cd,bus=ide.1,unit=1,drive=drive-ide0-1-1,id=ide0-1-1 -netdev tap,fd=26,id=hostnet0 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=fa:16:3e:db:86:d4,bus=pci.0,addr=0x3 -chardev file,id=charserial0,path=/opt/stack/data/nova/instances/f3fdf038-ffad-4d66-a1a9-4cd2b83021c8/console.log -device isa-serial,chardev=charserial0,id=serial0 -chardev pty,id=charserial1 -device isa-serial,chardev=charserial1,id=serial1 -vnc 127.0.0.1:1 -k en-us -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
 
架构:
 

QEMU 支持两种操作模式:用户模式仿真和系统模式仿真。用户模式仿真 允许一个 CPU 构建的进程在另一个 CPU 上执行(执行主机 CPU 指令的动态翻译并相应地转换 Linux 系统调用)。系统模式仿真 允许对整个系统进行仿真,包括处理器和配套的外围设备。

在 x86 主机系统上仿真 x86 代码时,使用 QEMU 加速器 可以实现近似本地的性能。这让我们能够直接在主机 CPU 上执行仿真代码(在 Linux 上通过 kernel 模块执行)。

但是从技术角度看,QEMU 的有趣之处在于其快速、可移植的动态翻译程序。动态翻译程序 允许在运行时将用于目标(来宾)CPU 的指令转换为用于主机 CPU,从而实现仿真。这可以通过一种强制方法实现(将指令从一个 CPU 映射到另一个 CPU),但是情况并非总是这样简单,在某些情况下,根据所翻译的架构,可能需要使用多个指令或行为更改。

QEMU 实现动态翻译的方法是,首先将目标指令转换为微操作。这些微操作是一些编译成对象的 C 代码。然后构建核心翻译程序。它将目标指令映射到微操作以进行动态翻译。这不仅可产生高效率,而且还可以移植。

QEMU 的动态翻译程序还缓存了翻译后的代码块,使翻译程序的内存开销最小化。当初次使用目标代码块时,翻译该块并将其存储为翻译后的代码块。 QEMU 将最近使用的翻译后的代码块缓存在一个 16 MB 的块中。 QEMU 甚至可以通过在缓存中将翻译后的代码块变为无效来支持代码的自我修改。

 

3、libvirt

Libvirt 库是一种实现 Linux 虚拟化功能的 Linux® API,它支持各种虚拟机监控程序。
 
libvirt是一个统一的虚拟化管理接口,当前支持的虚拟化实现如下:
  • The KVM/QEMU Linux hypervisor
  • The Xen hypervisor on Linux and Solaris hosts.
  • The LXC Linux container system
  • The OpenVZ Linux container system
  • The User Mode Linux paravirtualized kernel
  • The VirtualBox hypervisor
  • The VMware ESX and GSX hypervisors
  • The VMware Workstation and Player hypervisors
  • The Microsoft Hyper-V hypervisor
  • The IBM PowerVM hypervisor
  • The Parallels hypervisor
  • The Bhyve hypervisor
第一个就是QEMU,libvirt的virsh是可以传递QEMU的监控命令的,我希望实现的那个blueprint就是用libvirt去传递QEMU的监控命令,开启QEMU的内存使用统计,然后再通过libvirt获取虚拟机的内存使用情况。[by 参考1原文作者]
架构:
     
libvirt 比较和用例模型
     图中还显示了 libvirt 所用术语对照。这些术语很重要,因为在对 API 命名时会用到它们。两个根本区别在于,libvirt 将物理主机称作节点,将来宾操作系统称作域。这里需要注意的是,libvirt(及其应用程序)在宿主 Linux 操作系统(域 0)中运行。
 
控制方式:
     使用 libvirt,我们有两种不同的控制方式。第一种如 图 1 所示,其中管理应用程序和域位于同一节点上。 在本例中,管理应用程序通过 libvirt 工作,以控制本地域。当管理应用程序和域位于不同节点上时,便产生了另一种控制方式。在本例中需要进行远程通信(参见 图 2)。该模式使用一种运行于远程节点上、名为 libvirtd 的特殊守护进程。当在新节点上安装 libvirt 时该程序会自动启动,且可自动确定本地虚拟机监控程序并为其安装驱动程序(稍后讨论)。该管理应用程序通过一种通用协议从本地 libvirt 连接到远程 libvirtd。对于 QEMU,协议在 QEMU 监视器处结束。QEMU 包含一个监测控制台,它允许检查运行中的来宾操作系统并控制虚拟机(VM)各部分。
     
图 使用 libvirtd 控制远程虚拟机监控程序
 
虚拟机监控程序支持:
 
     为支持各种虚拟机监控程序的可扩展性,libvirt 实施一种基于驱动程序的架构,该架构允许一种通用的 API 以通用方式为大量潜在的虚拟机监控程序提供服务。这意味着,一些虚拟机监控程序的某些专业功能在 API 中不可见。另外,有些虚拟机监控程序可能不能实施所有 API 功能,因而在特定驱动程序内被定义为不受支持。图 3 展示了 libvirt API 与相关驱动程序的层次结构。这里也需要注意,libvirtd 提供从远程应用程序访问本地域的方式。
 
表 1. libvirt 支持的虚拟机监控程序
虚拟机监控程序 描述
Xen 面向 IA-32,IA-64 和 PowerPC 970 架构的虚拟机监控程序
QEMU 面向各种架构的平台仿真器
Kernel-based Virtual Machine (KVM) Linux 平台仿真器
Linux Containers(LXC) 用于操作系统虚拟化的 Linux(轻量级)容器
OpenVZ 基于 Linux 内核的操作系统级虚拟化
VirtualBox x86 虚拟化虚拟机监控程序
User Mode Linux 面向各种架构的 Linux 平台仿真器
Test 面向伪虚拟机监控程序的测试驱动器
Storage 存储池驱动器(本地磁盘,网络磁盘,iSCSI 卷)
 
 

参考:

KVM,QEMU,libvirt入门学习笔记【转】的更多相关文章

  1. Hadoop入门学习笔记---part4

    紧接着<Hadoop入门学习笔记---part3>中的继续了解如何用java在程序中操作HDFS. 众所周知,对文件的操作无非是创建,查看,下载,删除.下面我们就开始应用java程序进行操 ...

  2. Hadoop入门学习笔记---part3

    2015年元旦,好好学习,天天向上.良好的开端是成功的一半,任何学习都不能中断,只有坚持才会出结果.继续学习Hadoop.冰冻三尺,非一日之寒! 经过Hadoop的伪分布集群环境的搭建,基本对Hado ...

  3. PyQt4入门学习笔记(三)

    # PyQt4入门学习笔记(三) PyQt4内的布局 布局方式是我们控制我们的GUI页面内各个控件的排放位置的.我们可以通过两种基本方式来控制: 1.绝对位置 2.layout类 绝对位置 这种方式要 ...

  4. PyQt4入门学习笔记(一)

    PyQt4入门学习笔记(一) 一直没有找到什么好的pyqt4的教程,偶然在google上搜到一篇不错的入门文档,翻译过来,留以后再复习. 原始链接如下: http://zetcode.com/gui/ ...

  5. Hadoop入门学习笔记---part2

    在<Hadoop入门学习笔记---part1>中感觉自己虽然总结的比较详细,但是始终感觉有点凌乱.不够系统化,不够简洁.经过自己的推敲和总结,现在在此处概括性的总结一下,认为在准备搭建ha ...

  6. Hadoop入门学习笔记---part1

    随着毕业设计的进行,大学四年正式进入尾声.任你玩四年的大学的最后一次作业最后在激烈的选题中尘埃落定.无论选择了怎样的选题,无论最后的结果是怎样的,对于大学里面的这最后一份作业,也希望自己能够尽心尽力, ...

  7. Scala入门学习笔记三--数组使用

    前言 本篇主要讲Scala的Array.BufferArray.List,更多教程请参考:Scala教程 本篇知识点概括 若长度固定则使用Array,若长度可能有 变化则使用ArrayBuffer 提 ...

  8. OpenCV入门学习笔记

    OpenCV入门学习笔记 参照OpenCV中文论坛相关文档(http://www.opencv.org.cn/) 一.简介 OpenCV(Open Source Computer Vision),开源 ...

  9. KVM+Qemu+Libvirt实战

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

随机推荐

  1. 自定义smokeping告警(邮件+短信)

    前段时间接到公司IT同事需求,帮助其配置smokeping的告警功能,之前配置的姿势有些问题,告警有些问题,现在调试OK,在此将关键配置点简单记录下. 关键的配置项主要有: 定义告警规则并配置将告警信 ...

  2. 【转】LINQ多表关联关联条件

    转:http://www.dingcankong.com/linq%E4%B8%A4%E8%A1%A8%E8%81%94%E5%90%88%E6%9F%A5%E8%AF%A2/ 答案如下: var m ...

  3. 【刷题】BZOJ 4443 [Scoi2015]小凸玩矩阵

    Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最 ...

  4. linux 第三周读书笔记-----第一二章 20135334赵阳林

    第一章 Linux内核简介 1.1 Unix的历史 由于Unix系统设计简洁并且在发布时提供源代码,所以许多其他组织和团体都对它进了进一步的开发. Unⅸ虽然已经使用了40年,但计算机科学家仍然认为它 ...

  5. 20165218 《网络对抗技术》Exp3 免杀原理与实践

    Exp3 免杀原理与实践 任务一:正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己利用shellcode编程等免杀工具或技巧 使用VirusTotal或 ...

  6. WEB入门.六 盒子模型

    学习内容 CSS盒子模型 盒子之间的关系 页面元素定位 能力目标 理解盒子模型 理解内容与表现分离的优点 理解并掌握盒子之间的关系 理解并掌握绝对定位与相对定位的用法 本章简介 上一章节中已经讲解了页 ...

  7. CentOS 6.6搭建LNMP环境

    一.安装前 1.关闭linux的安全机制 vim /etc/selinux/config SELINUX=enforcing  改为  SELINUX=disabled 2.关闭iptables防火墙 ...

  8. MySQL 第八篇:ORM框架SQLAlchemy

    一 介绍 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取 ...

  9. ASP.NET MVC 3 常用

    http://blog.csdn.net/churujianghu/article/details/7297358 1.ASP.NET MVC 3 如何去除默认验证 这个默认验证是在web.confi ...

  10. intval floatval

    intval -- 获取变量的整数值 floatval -- 获取变量的浮点值 <?php $a = ; $b = ; $a/=$b; echo intval($a); echo floatva ...