zoukankan      html  css  js  c++  java
  • [转]HyperV 虛擬化技術(HyperV 2.0)

    源地址:http://www.dotblogs.com.tw/daniel07793/archive/2012/04/09/71362.aspx

    ======================================================

    在談這東西之前,就一定要先聊聊,Hypervisor這東西

    不論是VMWare vSphere,或是Hyper-V,都一定會有這東西

    這是Guest OS存取Hardware必定經過的一層,另一個名稱叫做Virtual Machine Monitor

    首先,先來看看有啟用Hyper-V跟沒有啟用Hyper-V的開機差異

    enable_Hyper

    (左圖是未啟用Hyper-V、右圖是啟用Hyper-V)

    當Hypervisor被啟用之後,將會使用%Systemroot%\System32\Drivers底下的hvboot.sys先載入Hypervisor

    hyper-v_boot

    接著在透過實際的CPU來決定使用哪一種VT技術,%Systemroot%\System32底下的hvax64.exe或者hvix64.exe

    hvax64.exe是AMD-V,hvix.64.exe是Intel-VT

    intelvt

    AMDVT

    啟用了Hyper-V之後,將會使用Hypervisor去存取Hardware的CPU與Memory

    接著,才會取啟動Host Server(在Hyper-V中稱為Parent Partition),又稱為父分割區

    在啟用Hyper-V之後,Host將會處於下圖VM1中的位置,後續所建立的Guest OS,將會在VM2與VM3的位置

    又稱為Child Partition,子分割區

    hyper-v

    從上圖可以看到,Child Partition都會需要安裝Driver才能存取像是Ethemet、Hard Drive、Time Sync…等等的一些裝置

    然而會有很多VMWare ESX的使用者會說,在VMWare ESX裡的Guest OS就不需要安裝就能夠使用了

    這是因為這兩者的Hypervisor的結構本身並不相同,VMWare ESX使用的是感知型的Hypervisor Drivers

    所以會需要硬體支援(硬體廠商配合VMWare開發),但是Hyper-V則是Host有支援即可(有驅動就可以)

    (下圖為VMWare ESX的Hypervisor)

    VMWare

    雖然VMWare可以在未安裝VM Tools的情況下運作,但是還是安裝後才能得到更多進階的功能

    因為此篇主要是講解Hyper-V,在此就不對VMWare的部份有過多的說明囉~

    下面這張圖,將說明啟用前跟啟用後的差異

    hyper-v_enable

    下圖,則是Parent跟Child之間的關係,在VMBus可溝通的情況下,將會使用Hypercall對Hypervisor進行I/O

    hyper-v-role

    Virtual Machine Worker Process(VMWP)就相當於是Guest OS的主機板

    vmwp

    VMWP會使用VMBUS、VID去使用Hypervisor API去對Hypervisor存取,取得Guest OS該使用的資源

    112

    12345

    Virtualization infrastructure Driver其實就是%Systemroot%\System32\Drivers底下的winhv.sys

    hvinf

    VSC

    當Guest OS在存取VHD時,則會透過VSC,經過VMBUS連接父分割區的VMBUS,由父分割區的VSP進行DISK I/O

    storage

    這是比較詳細的I/O運作邏輯

    43

    這是Driver透過VMBUS的對應

    VMDevice

    在此引用這個網站的圖片,來做一個簡單的圖解

    http://www.msservermag.com.tw/technicwords/021128.aspx

    01

    微軟的MSDN中,有提供Hyper-V WMI Provider的文件可以參考

    http://msdn.microsoft.com/en-us/library/cc136992(VS.85).aspx

    在啟用Hyper-V後,會新增root\virtualization這個命名空間,我們可以透過PowerShell去查詢該命名空間底下所有的Object

    指令是Get-Wmiobject –Namespace “root\virtualization” –Computer Hostname –list

    WMI2

    下圖這個範例,示範了如何透過WMI去查詢Guest OS的狀態

    Get-WmiObject -Class Msvm_ComputerSystem -Namespace "root\virtualization" -ComputerName Hostname

    其中的EnabledState就是回傳的狀態值,2代表正常

    wmi

    這邊看似沒甚麼了不起,GUI介面就可以得知的東西

    呃…確實是如此,因為GUI介面就已經幫你寫好查詢的方法跟回傳,這裡只是大概講解Hyper-V Manager

    是如何去取得Guest OS的狀態之類

    但是如果是GUI介面所沒有的呢:P

    或者你要用Job的方式從Host去控制Guest OS,而不是透過Guest OS的Job去控制呢?

    這裡的命令,其實都是透過WMI去控制的

    WMI3

    接著來示範一個很奇特的範例,來驗證第一張圖,WMI的架構

    我們先透過一個VBScript去使用Windows Script Host去呼叫CIMOM

    然後,對Guest OS做鍵盤輸入的動作,首先先將下列VBScript存成PressKey.vbs

    如對此VBScript不放心,您可以直接至Microsoft MSDN中複製

    http://msdn.microsoft.com/en-us/library/cc136956(v=vs.85).aspx

    001 option explicit
    002  
    003 dim objWMIService
    004 dim fileSystem
    005 const wmiSuccessful = 0
    006  
    007 Main()
    008  
    009 '-----------------------------------------------------------------
    010 ' Main routine
    011 '-----------------------------------------------------------------
    012 Sub Main()
    013      
    014     dim computer, objArgs, vmName, computerSystem, keycode, keyboard
    015      
    016     set fileSystem = Wscript.CreateObject("Scripting.FileSystemObject")
    017  
    018     computer = "."
    019     set objWMIService = GetObject("winmgmts:\\" & computer & "\root\virtualization")
    020  
    021     set objArgs = WScript.Arguments
    022     if WScript.Arguments.Count = 2 then
    023        vmName= objArgs.Unnamed.Item(0)
    024        keycode = objArgs.Unnamed.Item(1)
    025     else
    026        WScript.Echo "usage: cscript PressKey.vbs vmName keycode"
    027        WScript.Quit
    028     end if
    029      
    030     set computerSystem = GetComputerSystem(vmName)
    031     set keyboard = GetComputerKeyboard(computerSystem)
    032  
    033     if PressKey(keyboard, keycode) then
    034  
    035         WriteLog "Done"
    036         WScript.Quit(0)
    037     else
    038         WriteLog "PressKey failed"
    039         WScript.Quit(1)
    040     end if
    041  
    042 End Sub
    043  
    044 '-----------------------------------------------------------------
    045 ' Retrieve Msvm_VirtualComputerSystem from base on its ElementName
    046 '
    047 '-----------------------------------------------------------------
    048 Function GetComputerSystem(vmElementName)
    049     dim query
    050     On Error Resume Next
    051     query = Format1("select * from Msvm_ComputerSystem where ElementName = '{0}'", vmElementName)
    052     set GetComputerSystem = objWMIService.ExecQuery(query).ItemIndex(0)
    053     if (Err.Number <> 0) then
    054         WriteLog Format1("Err.Number: {0}", Err.Number)
    055         WriteLog Format1("Err.Description:{0}",Err.Description)
    056         WScript.Quit(1)
    057     end if
    058 End Function
    059  
    060  
    061 '-----------------------------------------------------------------
    062 ' Retrieve Msvm_Keyboard from given computer system
    063 '
    064 '-----------------------------------------------------------------
    065 Function GetComputerKeyboard(computerSystem)
    066     dim query
    067     On Error Resume Next
    068     query = Format1("ASSOCIATORS OF {{0}} WHERE resultClass = Msvm_Keyboard", computerSystem.Path_.Path)
    069     set GetComputerKeyboard = objWMIService.ExecQuery(query).ItemIndex(0)
    070     if (Err.Number <> 0) then
    071         WriteLog Format1("Err.Number: {0}", Err.Number)
    072         WriteLog Format1("Err.Description:{0}",Err.Description)
    073         WScript.Quit(1)
    074     end if
    075 End Function
    076  
    077 '-----------------------------------------------------------------
    078 ' Press the key with the given key code on the given keyboard
    079 '-----------------------------------------------------------------
    080 Function PressKey(keyboard, keyCode)
    081     WriteLog Format2("PressKey({0}, {1})", keyboard.ElementName, keyCode)
    082      
    083     dim objInParam, objOutParams
    084      
    085     PressKey = false
    086     set objInParam = keyboard.Methods_("PressKey").InParameters.SpawnInstance_()
    087     objInParam.keyCode = keyCode
    088  
    089     set objOutParams = keyboard.ExecMethod_("PressKey", objInParam)
    090  
    091     if objOutParams.ReturnValue = wmiSuccessful then
    092         WriteLog Format2("The key with code '{0}' is typed on {1}.", keyCode, keyboard.ElementName)
    093         PressKey = true
    094     end if
    095  
    096 End Function
    097  
    098 '-----------------------------------------------------------------
    099 ' Create the console log files.
    100 '-----------------------------------------------------------------
    101 Sub WriteLog(line)
    102     dim fileStream
    103     set fileStream = fileSystem.OpenTextFile(".\PressKey.log", 8, true)
    104     WScript.Echo line
    105     fileStream.WriteLine line
    106     fileStream.Close
    107  
    108 End Sub
    109  
    110  
    111 '------------------------------------------------------------------------------
    112 ' The string formatting functions to avoid string concatenation.
    113 '------------------------------------------------------------------------------
    114 Function Format2(myString, arg0, arg1)
    115     Format2 = Format1(myString, arg0)
    116     Format2 = Replace(Format2, "{1}", arg1)
    117 End Function
    118  
    119 '------------------------------------------------------------------------------
    120 ' The string formatting functions to avoid string concatenation.
    121 '------------------------------------------------------------------------------
    122 Function Format1(myString, arg0)
    123     Format1 = Replace(myString, "{0}", arg0)
    124 End Function

    接著我們會需要這張表去對應Virtial Key相對應的Uint32的值

    http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx

    這張表的值是16進位,將其換算成十進位後,加上256,會可以輸入該值到Guest OS中

    像範例中,我會Daniel-AD這部Guest OS輸入鍵盤324,d這個字母在表列中為0x44

    也就是256+68=324,接著他就會在Guest OS中輸入d這個字母

    WMI4

    你也可以透過Powershell去轉換這個數值

    PowerShell的語法function To-UInt32{[UInt32]("0x{0:x}" -f $args[0])+256}

    這可以新增一個To UInt32的轉換方法

    接著可以透過To-UInt32 0x44去取得相對應的值

    WMI5

  • 相关阅读:
    Redis 外网无法访问
    设计模式单例模式
    网易笔试问答(20210328)新生代转移到老年代的情况
    网易笔试(20210327)最长摇摆子数组长度
    网易笔试(20210327)吉利数(子数组中数组和为6的倍数的最大子数组和)
    360笔试(20210328)射气球
    解决TFS 错误:[TF15013 请求的 Team Foundation Server 未向代理服务器注册]
    TFS 常用命令
    生成安全的用于加密的随机数
    一种新的验证码(改进版)
  • 原文地址:https://www.cnblogs.com/licheng/p/2978675.html
Copyright © 2011-2022 走看看