一文讀懂QEMU虛擬機

Qemu 架構

Qemu 是純軟件實現的虛擬化模擬器,幾乎可以模擬任何硬件設備,我們最熟悉的就是能夠模擬一臺能夠獨立運行操作系統的虛擬機,虛擬機認爲自己和硬件打交道,但其實是和 Qemu 模擬出來的硬件打交道,Qemu 將這些指令轉譯給真正的硬件。

正因爲 Qemu 是純軟件實現的,所有的指令都要經 Qemu 過一手,性能非常低,所以,在生產環境中,大多數的做法都是配合 KVM 來完成虛擬化工作,因爲 KVM 是硬件輔助的虛擬化技術,主要負責 比較繁瑣的 CPU 和內存虛擬化,而 Qemu 則負責 I/O 虛擬化,兩者合作各自發揮自身的優勢,相得益彰。

qemu

從本質上看,虛擬出的每個虛擬機對應 host 上的一個 Qemu 進程,而虛擬機的執行線程(如 CPU 線程、I/O 線程等)對應 Qemu 進程的一個線程。下面通過一個虛擬機啓動過程看看 Qemu 是如何與 KVM 交互的。

 

// 第一步,獲取到 KVM 句柄
kvmfd = open("/dev/kvm", O_RDWR);
// 第二步,創建虛擬機,獲取到虛擬機句柄。
vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
// 第三步,爲虛擬機映射內存,還有其他的 PCI,信號處理的初始化。ioctl(kvmfd, KVM_SET_USER_MEMORY_REGION, &mem);
// 第四步,將虛擬機鏡像映射到內存,相當於物理機的 boot 過程,把鏡像映射到內存。
// 第五步,創建 vCPU,併爲 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);
// 第六步,線程進入循環,並捕獲虛擬機退出原因,做相應的處理。
for (;;) {  
  ioctl(KVM_RUN)  
  switch (exit_reason) {      
    case KVM_EXIT_IO:  /* ... */      
    case KVM_EXIT_HLT: /* ... */  
  }
}
// 這裏的退出並不一定是虛擬機關機,
// 虛擬機如果遇到 I/O 操作,訪問硬件設備,缺頁中斷等都會退出執行,
// 退出執行可以理解爲將 CPU 執行上下文返回到 Qemu。

Qemu 源碼結構

Qemu 軟件虛擬化實現的思路是採用二進制指令翻譯技術,主要是提取 guest 代碼,然後將其翻譯成 TCG 中間代碼,最後再將中間代碼翻譯成 host 指定架構的代碼,如 x86 體系就翻譯成其支持的代碼形式,ARM 架構同理。

所以,從宏觀上看,源碼結構主要包含以下幾個部分:

  • /vl.c:最主要的模擬循環,虛擬機環境初始化,和 CPU 的執行。

  • /target-arch/translate.c:將 guest 代碼翻譯成不同架構的 TCG 操作碼。

  • /tcg/tcg.c:主要的 TCG 代碼。

  • /tcg/arch/tcg-target.c:將 TCG 代碼轉化生成主機代碼。

  • /cpu-exec.c:主要尋找下一個二進制翻譯代碼塊,如果沒有找到就請求得到下一個代碼塊,並且操作生成的代碼塊。

其中,涉及的主要幾個函數如下:

知道了這個總體的代碼結構,再去具體瞭解每一個模塊可能會相對容易一點。

Qemu 的使用

1. 源碼下載

 

直接安裝
ubuntu:sudo apt-get install qemu
centos:sudo yum install qemu -y
下載安裝包:
$wget http://wiki.qemu-project.org/download/qemu-2.0.0.tar.bz2
$tar xjvf qemu-2.0.0.tar.bz2
Git:
$git clone git://git.qemu-project.org/qemu.git

2. 編譯及安裝

 

$cd qemu-2.0.0 //如果使用的是git下載的源碼,執行cd qemu
$./configure --enable-kvm --enable-debug --enable-vnc --enable-werror  --target-list="x86_64-softmmu"
$make -j8
$sudo make install

configure 腳本用於生成 Makefile,其選項可以用 ./configure --help 查看。

這裏使用到的選項含義如下:

  • --enable-kvm:編譯 KVM 模塊,使 Qemu 可以利用 KVM 來訪問硬件提供的虛擬化服務。

  • --enable-vnc:啓用 VNC。

  • --enalbe-werror:編譯時,將所有的警告當作錯誤處理。

  • --target-list:選擇目標機器的架構。默認是將所有的架構都編譯,但爲了更快的完成編譯,指定需要的架構即可。

安裝好之後,會生成如下應用程序:

  • ivshmem-client/server:這是一個 guest 和 host 共享內存的應用程序,遵循 C/S 的架構。

  • qemu-ga:這是一個不利用網絡實現 guest 和 host 之間交互的應用程序(使用 virtio-serial),運行在 guest 中。

  • qemu-io:這是一個執行 Qemu I/O 操作的命令行工具。

  • qemu-system-x86_64:Qemu 的核心應用程序,虛擬機就由它創建的。

  • qemu-img:創建虛擬機鏡像文件的工具,下面有例子說明。

  • qemu-nbd:磁盤掛載工具。

下面通過創建虛擬機操作來對這些工具有個初步的認識。

3. 創建虛擬機

  • 使用qemu-img創建虛擬機鏡像

虛擬機鏡像用來模擬虛擬機的硬盤,在啓動虛擬機之前需要創建鏡像文件。

 

qemu-img create -f qcow2 test-vm-1.qcow2 10G

-f 選項用於指定鏡像的格式,qcow2 格式是 Qemu 最常用的鏡像格式,採用來寫時複製技術來優化性能。test-vm-1.qcow2 是鏡像文件的名字,10G是鏡像文件大小。鏡像文件創建完成後,可使用 qemu-system-x86 來啓動x86 架構的虛擬機:

  • 使用 qemu-system-x86 來啓動 x86 架構的虛擬機

 

qemu-system-x86_64 test-vm-1.qcow2

因爲 test-vm-1.qcow2 中並未給虛擬機安裝操作系統,所以會提示 “No bootable device”,無可啓動設備。

  • 啓動 VM 安裝操作系統鏡像

 

qemu-system-x86_64 -m 2048 -enable-kvm test-vm-1.qcow2 -cdrom ./Centos-Desktop-x86_64-20-1.iso

-m 指定虛擬機內存大小,默認單位是 MB, -enable-kvm 使用 KVM 進行加速,-cdrom 添加 fedora 的安裝鏡像。可在彈出的窗口中操作虛擬機,安裝操作系統,安裝完成後重起虛擬機便會從硬盤 ( test-vm-1.qcow2 ) 啓動。之後再啓動虛擬機只需要執行:

 

qemu-system-x86_64 -m 2048 -enable-kvm test-vm-1.qcow2

qemu-img 支持非常多種的文件格式,可以通過 qemu-img -h 查看

其中 raw 和 qcow2 是比較常用的兩種,raw 是 qemu-img 命令默認的,qcow2 是 qemu 目前推薦的鏡像格式,是功能最多的格式。這些知識後面會有文章來專門講述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章