虚拟机内关键技术的研究Word文档格式.docx
《虚拟机内关键技术的研究Word文档格式.docx》由会员分享,可在线阅读,更多相关《虚拟机内关键技术的研究Word文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
![虚拟机内关键技术的研究Word文档格式.docx](https://file1.bdocx.com/fileroot1/2022-12/13/65e03d5c-d36f-43dd-8550-ff7c0aa90fd9/65e03d5c-d36f-43dd-8550-ff7c0aa90fd91.gif)
从而需要执行2个地址翻译过程:
操作系统将VA翻译为PA,VMM将PA翻译为MA。
经过一系列变换实现内存的虚拟化。
1.4I/O虚拟化
目前虚拟机中存I/O虚拟化的实现可分为VMM-basedI/O、Host-basedI/O、和DirectI/O等多种方式。
以下是这几种的基本模型
VMM-basedI/O
该模型中由ⅥI皿实现对物理I/0设备的驱动。
与此同时,VMM为每个VM模拟一个独享的设备,该模拟设备和物理设备可以不同,这样性能更加优异,但由于I/O设备的多样性和复杂性,利用这种虚拟I/O就增加了开发维护的繁重性,对于个人设备而言一般采用Host-basedI/O
Host-basedI/O
由于现在操作系统已经对I/O设备提供充分的支持,完全可以借助操作系统的驱动来访问I/O设备实现。
这样简化了设计,但由于要间接调用,开销加大,xen中就借助批处理方法,一次发送多个I/O请求来减少处理开销,充分提高I/O吞吐量。
DirectI/O
虚拟机的host-basedI/O模型和VMM-basedI/O模型难以满足高性能计算的需求。
为了减少通信延迟,可借鉴OS-Bypass的思想,让运行在OS上的应用程序绕过OS和VMM直接访问I/O设备,这种方式称为DirectI/O。
这种模型的实现需要I/O设备的支持,种模型在高性能计算领域具有良好应用前景。
系统硬件对I/O设备虚拟化的支持
基于软件方式实现I/0虚拟化存在安全隔离和性能两方面的问题:
虚拟机系统中一个VM可通过I/O设备的DMA操作访问到其它VM的空间,因此无法实现彻底隔离;
另一方面,GuestOS对设备的访问都要经过VMM,影响了I/O性能。
通过硬件方式实现I/O虚拟化则可以有效解决这些问题。
,因此VM直接访问设备时不再需要VMM进行地址翻译。
IOMMU的不足之处在于无法支持多个VM对设备的共享,这一问题可能会在PCI-SIG规范中得到解决。
2、Xen相关介绍
Xen是一个开放源代码的para-virtualizing虚拟机(VMM),或“管理程序”,是为x86架构的机器而设计的。
Xen可以在一套物理硬件上安全的执行多个虚拟机;
Xen是基于内核的虚拟程序,它和操作平台结合的极为密切,所以它占用的资源最少。
因为Xen是基于内核的,相对VMWARE来说,它占用的系统资源也就是VMWARE的百分之几左右。
而且虚拟机的性能更接近真实硬件环境在真实物理环境的平台和虚拟平台间自由切换,在每个客户虚拟机支持到32个虚拟CPU,通过VCPU热插拔)支持PAE指令集的x86/32,x86/64平台
通过Intel虚拟支持VT的支持来用虚拟原始操作系统(未经修改的)支持(包括MicrosoftWindows)优秀的硬件支持.支持几乎所有的Linux设备驱动。
Xen的应用范围相当广泛:
服务器整合:
在虚拟机范围内,在一台物理主机上安装多个服务器,用于演示及故障隔绝;
无硬件依赖:
允许应用程序和操作系统对新硬件的移值测试;
多操作系统配置:
以开发和测试为目的,同时运行多个操作系统;
内核开发:
在虚拟机的沙盒中,做内核的测试和调试,无需为了测试而单独架设一台独立的机器;
集群运算:
和单独的管理每个物理主机相比较,在VM级管理更加灵活,在负载均衡方面,更易于控制,和隔离;
为客户操作系统提供硬件技术支持:
可以开发新的操作系统,以得益于现存操作系统的广泛硬件支持,比如Linux;
基于Xen的操作系统,有多个层,最底层和最高特权层是Xen程序本身。
Xen可以管理多个客户操作系统,每个操作系统都能在一个安全的虚拟机中实现。
在Xen的术语中,Domain由Xen控制,以高效的利用CPU的物理资源。
每个客户操作系统可以管理它自身的应用。
这种管理包括每个程序在规定时间内的响应到执行,是通过Xen调度到虚拟机中实现。
当Xen启动运行后,第一个虚拟的操作系统,就是Xen本身,我们通过xmlist,会发现有一个Domain0的虚拟机。
Domain0是其它虚拟主机的管理者和控制者,Domain0可以构建其它的更多的Domain,并管理虚拟设备。
它还能执行管理任务,比如虚拟机的体眠、唤醒和迁移其它虚拟机。
一个被称为xend的服务器进程通过domain0来管理系统,Xend负责管理众多的虚拟主机,并且提供进入这些系统的控制台。
命令经一个命令行的工具通过一个HTTP的接口被传送到xend。
3、XEN的安装
3.1安装要求
拥有GRUB引导的Linux做为安装平台,还要编译工具,比如gcc、binutils及make和automake等;
开发库有zlib和python-dev等;
由于Xen用Python开发的,所以Python当然也是必不可少的。
如果您是新手,我建议您用自己所用的操作系统软件包管理工具来安装这些软件包。
3.2Xen在ubuntu下的安装
<
1>
安装编译Xen和Linuxxenkernel所需要的软件包:
通过一下命令安装必要环境:
$sudoapt-getinstallgccg++makepatchlibssl-devbzip2gettext\
zlib1g-devpythonlibncurses5-devlibjpeg62-devlibx11-dev\
libgcrypt11-devpkg-configbridge-utilsbccbin86libpci-dev\
libsdl-devpython-devtexinfolibc6-devuuid-devbisonflexfakeroot\
build-essentialcrashkexec-toolsmakedumpfilelibncurses5\
libncurses5-deviaslgawk
$sudoapt-getbuild-deplinux
<
2>
安装Xenhypervisor和tools
到http:
//xen.org/products/xen_source.html下载最新的Xen源代码,然后解开、编译、安装,标准的Linux软件源码安装动作:
$tarzxvfxen-4.0.0.tar.gz
$cdxen-4.0.0/
$makexentoolsstubdom
$sudomakeinstall-xeninstall-toolsinstall-stubdom
makestubdom的时候会从网上自动下载一些东西,所以如果是用代理上网的话需要在自己根目录下的.wgetrc里加上代理服务器,以便wget能通过代理正常下载:
$vi.wgetrc
http_proxy=:
3128/
use_proxy=on
加入到自动启动脚本中:
$sudoupdate-rc.dxenddefaults2021
$sudoupdate-rc.dxendomainsdefaults2120
3>
安装Xen内核
下载xen内核,给内核打补丁:
$cd
$wgethttp:
//www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.31.8.tar.bz2
$tar-xjflinux-2.6.32.8.tar.bz2
//gentoo-xen-
$mkdirxenpatch-2.6.32.8
$cdxenpatch-2.6.32.8
$tar-xjf../xen-patches-2.6.32-10.tar.bz2
$cd..
$cdlinux-2.6.32.8
$foriin`ls../xenpatch-2.6.32.8/`;
dopatch-p1<
../xenpatch-2.6.32.8/"
$i"
;
done
配置内核,直接把系统已经存在的配置文件拷过来然后在此基础上修改:
$cp/boot/config-2.6.32-14-server.config
$makemenuconfig
Processortypeandfeatures--->
[*]EnableXencompatiblekernel
Networkingsupport--->
Networkingoptions--->
*>
802.1dEthernetBridging
DeviceDrivers--->
XEN--->
[*]PrivilegedGuest(domain0)
Backenddriversupport
Block-devicebackenddriver
Block-devicetapbackenddriver
Block-devicetapbackenddriver2
Network-devicebackenddriver
PCI-devicebackenddriver
SCSIbackenddriver
USBbackenddriver
Block-devicefrontenddriver
Network-devicefrontenddriver
SCSIfrontenddriver
USBfrontenddriver
Framebuffer-devicefrontenddriver
Keyboard-devicefrontenddriver
[*]Disableserialportdrivers
ExportXenattributesinsysfs
Xenversioncompatibility(4.1.2andlater)--->
4.1.2andlater
配置好内核参数以后,保存配置文件、退出配置界面就可以开始编译Linux内核了:
$make
$sudomakeinstall
$sudomakemodules_install
$sudoupdate-initramfs-c-k2.6.32.8
$sudodepmod2.6.32.8
如果Xen加了内核模块的话加入/etc/modules文件以便启动时候自动加载:
$sudovi/etc/modules
...
netbk
blkbk
有时Xen不能正常启动,删除grub2.0换成老版本的grub:
$sudoapt-getpurgegrub-pc
$sudorm/boot/grub/*
$sudoapt-getinstallgrub
$sudogrub-install--recheck/dev/sda
$sudoupdate-grub
$sudovi/boot/grub/menu.lst
重新启动系统,就应该可以进入dom0了:
$sudoreboot
4>
引导Xen操作系统
引导系统进入Xen将要带你进入一个特权的domain管理,Domain0。
在这时,您可以创建客户domain,并通过xmcreate命令来引导他们。
(其实每个被虚拟的操作系统,都会产生一个Domain。
一般说来,每个Domain就是一个虚拟的操作系统。
当用支持Xen的内核启动时,系统会自动创建一个拥有超级权限的Domain0,这个Domain0负责管理硬件和为虚拟操作系统提供虚拟硬件环境。
从Domain0开始引导
当我们安装和配置完成,并重新引导系统,就可以在GRUB的启动菜单上选择有支持Xen的启动项来启动系统。
用Xen支持的内核启动,看起来有点象Linux常规引导。
第一部份输出的是Xen本身的信息,这些信息是关于Xen自身和底层的硬件的信息。
最后的输出是来自于XenLinux。
当引导完成后,您应该可以登录您的操作系统了。
如果不能登录,应该使用普通内核(也就是原来没有Xen的那个内核--译者注)来引导。
然后进行一些问题排查。
创建一个新的Domain的首先要准备一个root文件系统,这个文件系统可以是一个物理分区,一个LVM或其它的逻辑卷分区,映像文件,或在一个NFS服务器上。
最简单的是通过操作系统的安装盘把操作系统安装进另一个物理分区。
启动xend守护进程,请输入如下命令:
#xendstart
如果您想让xend服务器守护程序开机自动运行,可以通过设置启动项来实现自启动。
一旦xend运行起来就可以使xm工具来监视、管理、运行系统中的Domain。
另外一些配置可以参考《Xen用户手册》。
4、一些应用
4.1存储和文件系统管理
对于虚拟机来说有几种存储方法,最常用的,最简单的方法是以物理块设备(一个硬盘或分区)做为虚拟系统的块设备。
也可以用一个映像文件或已经分割的文件系统映像为做为虚拟系统的块设备。
最后,标准的网络存储协议,比如NBD,iSCSI,NFS等,也能做为虚拟系统的存储系统。
虚拟系统可以安装在物理硬盘或物理硬盘的分区上,也可以安装在一个映像文件上,也可以安装在一个映像文件的分区上,还可以安装到网络文件系统上。
把物理硬盘做为虚拟块设备
一个简单的配置就是直接把有效的物理分区做为虚拟块设备。
在您的domain配置文件中,通过用phy:
来指定。
比如类似下面的一行:
disk=['
phy:
hda3,sda1,w'
]
specifiesthatthepartition/dev/hda3indomain
0shouldbeexportedread-writetothenewdomainas/dev/sda1;
onecouldequallywellexportitas/dev/hdaor/dev/sdb5shouldonewish.
指定物理分区/dev/hda3虚拟为/dev/sda1,并且被虚拟的系统所用的文件系统位于/dev/sda1。
当然也可以虚拟为/dev/hda或/dev/sdb5,就看您想用哪个了。
因为被虚拟的操作系统用的是虚拟的文件系统,所以要通过phy:
来定义,首先定义的是物理分区,然后是虚拟分区(虚拟分区是根据自己喜欢而定义,但不能定义为正在应用的平台分区,比如您在Fedora5.0上虚拟Slackware,就不能用Fedora5.0的root分区做为Slackware的虚拟root分区),接着是读写规划,是可读可写的w,还是只读的r。
本地硬盘和分区,它能被做为能被Linux认可的硬件设备。
例如,如果您有一个iSCSI硬盘或GNBD逻辑卷,你也能用phy:
disksyntax来定义被虚拟系统的硬盘。
vg/lvm1,sda2,w'
块设备作为经典的配置在Domain中是只读的,否则Linux内核的文件系统由于Domain文件系统多次改变而变得混乱(相同的ext3分区以rw读写方式挂载两次的解决办法会导致崩溃的危险)!
。
Xend通过检查设备没有以rw可写读模式被挂载于Domain0上,并且检查同一个块设备没有以读写的方式应用于另一外一个Domain上;
等等应用都可以模拟。
总之,Xen用户很大,可以虚拟几乎所有硬件,来提供你所需的所有服务。
以下是相关的API介绍:
成员
说明
name
调度器名称,系统中实现了两个调度器:
sedf和credit,前者已经过时
init
调度器初始化
init_domain
在域创建时(sched_init_domain),这个回调函数负责设置域中调度器相关的数据结构
destroy_domain
在域析构时(sched_destroy_domain)
init_vcpu
在创建一个新的vcpu时(sched_init_vcpu),这个函数负责设置vcpu中调度器相关的数据结构
destroy_vcpu
在vcpu析构时(sched_destroy_vcpu)
Sleep
在sched_sleep_nosync中调用
Wake
在vcpu_wake中调用,这个函数一般会调用schedule
do_schedule
在schedule中调用
pick_cpu
在vcpu_migrate中调用
adjust
在sched_adjust中调用
dump_setting
在dump_runq中调用
dump_cpu_state
Xen并没有提供一个调度器注册函数,要添加新的调度器只能修改schedulers数组,目前这个数组中有如下成员:
staticstructscheduler*schedulers[]={
&
sched_sedf_def,
sched_credit_def,
NULL
}
task_slice,调度器用这个结构和调度核心接口,包括了下一个运行的VM以及运行的时间片大小:
structtask_slice{
structvcpu*task;
s_time_ttime;
当调度核心需要调度一个虚拟机时就会咨询当前的调度器,调度器通过返回这样的一个结构来确定下一个调度运行的虚拟机。
Xen的调度器核心为schedule函数,这个函数实现VM切换操作,主要逻辑如下:
staticvoidschedule(void)
{
structvcpu*prev=current;
next_slice=ops.do_schedule(now);
//咨询调度器,得到下一个需要调度的VM
r_time=next_slice.time;
//运行时间片
next=next_slice.task;
//下一个VM
set_timer(&
sd->
s_timer,now+r_time);
//定时
context_switch(prev,next);
set_current(next);
__context_switch();
schedule_tail(next);
//这一步完成切换
12
staticvoid__context_switch(void)
structcpu_user_regs*stack_regs=guest_cpu_user_regs();
if(!
is_idle_vcpu(p))
memcpy(&
p->
arch.guest_context.user_regs,
stack_regs,
CTXT_SWITCH_STACK_BYTES);
//保存现场
arch.ctxt_switch_from(p);
is_idle_vcpu(n))
memcpy(stack_regs,
n->
//恢复现场
arch.ctxt_switch_to(n);
schedule_tail函数完成最后的切换,不同的体系下,这个函数有不同的实现,但是都要调用reset_stack_and_jump:
#definereset_stack_and_jump(__fn)\
__asm____volatile__(\
"
mov%0,%%"
__OP"
sp;
jmp"
STR(__fn)\
:
:
"
r"
(guest_cpu_user_regs()):
memory"
)
这段代码进行栈帧的切换,最后根据__fn的不同将实现不同的功能:
有的__fn会调整栈帧,最后利用ret指令实现向栈帧中地址的跳转,例如在paravirt下;
有的__fn则读取栈帧中数据写入到另外的控制结构中,然后用别的方式实现切换,例如在hvm下;
有的__fn则是一个死循环,例如reset_stack_and_jump(idle_loop)中的idle_loop。
par