QEMU

出自 Arch Linux 中文维基

來自 QEMU 關於頁面:「QEMU」是一個廣泛使用的開源計算機模擬器和虛擬機。"

當作為模擬器時,可以在一種架構(如x86 PC)下運行另一種架構(如ARM)下的作業系統和程序。通過使用動態轉換,它可以獲得非常好的性能。

作為虛擬機時,QEMU可以使用其他虛擬機管理程序(如 XenKVM)來使用 CPU 擴展(HVM)進行虛擬化,通過在主機 CPU 上直接執行客户機代碼來獲得接近於宿主機的性能。

安裝[編輯 | 編輯原始碼]

安裝 qemu-full,(或 qemu-base,一個沒有GUI的版本)並根據需要安裝下面的可選軟件包:

除了這些之外, qemu-user-static 提供了 user-mode 下運行靜態編譯程序的支持。

QEMU 變種[編輯 | 編輯原始碼]

QEMU提供了多個變種以供用户在不同場景中使用。

粗略地説,QEMU 有兩種運行模式:

全系統模擬模式(full-system emulation)
在該模式下, QEMU 將會模擬一個完整的系統,包含一個或多個處理器以及各種外圍設備。這種模式更加貼近真實的系統,且這種模式不要求被模擬的客户機系統是 Linux,但它的速度較慢。
QEMU 中啟用 full-system 模式的命令依照如下規則進行命名 qemu-system-目標機器架構,例如 qemu-system-x86_64 用於模擬 x86_64 架構 CPU, qemu-system-i386 模擬 Intel 32位 x86 架構 CPU, qemu-system-arm 模擬 32 位 ARM 架構qemu-system-aarch64 模擬 64 位 ARM 架構,等等。
如果模擬的 CPU 架構與宿主機的 CPU 架構相同, 那麼即使在此模式下,QEMU 仍有可能使用 hypervisor(例如KVM 或者 Xen)的技術對模擬機進行加速。
用户模式(Usermode emulation)
在此模式下, QEMU 能夠利用宿主機的系統資源來調用為其他架構編譯的 Linux 可執行文件。當然,裏面依舊存在一些小問題, 比如説一些功能特性沒有被實現, 採用動態連結的可執行文件無法直接在上面使用(參閱#從x86_64環境中 Chroot 至 arm/arm64 環境解決該問題)並且只支持 Linux 程序(儘管我們可以使用wine在 Linux 上運行 Windows 程序)。
QEMU 中啟用用户模式的命令依照如下規則進行命名 qemu-目標機器架構, 例如 qemu-x86_64 用於模擬 64 位的 CPU。

QEMU 擁有動態連結和靜態連結兩個變種:

動態連結 (默認)
qemu-* 命令依賴於宿主機上的庫文件, 因此整個程序體積較小。
靜態連結
qemu-* 命令則可以在任何架構相同的 Linux 系統上使用。

在 Arch Linux 中,全系統模擬有兩個變種:

有界面(Non-Headless)(默認):這個變種啟用了一些 GUI 相關的特性,需要額外的依賴(例如 SDL 或 GTK)。
無界面(Headless):這個變種不需要 GUI 相關的依賴(適用於伺服器場景)。

需要注意的是,這兩個版本安裝的執行文件名稱是一樣的(例如 qemu-system-x86_64),因此系統上不能同時安裝這兩個版本。

Arch Linux中相關安裝包的詳細信息[編輯 | 編輯原始碼]

  • qemu-desktop 包提供了 x86_64 架構的模擬器, 可以進行全系統模擬 (qemu-system-x86_64)。 qemu-emulators-full包提供了 x86_64 用户模式的模擬 (qemu-x86_64)。 對於其他支持的架構,這個包都提供了全系統模擬和用户模擬兩個變種 (比如説 qemu-system-armqemu-arm)。
  • 對應於這些包的無界面版本 (僅適用於全系統模擬模式) 分別是 qemu-base(僅x86_64) 和 qemu-emulators-full (其餘架構)。
  • 可以用如下獨立的安裝包中的 QEMU 模塊擴展全系統模擬的功能: qemu-block-gluster, qemu-block-iscsi, 和 qemu-guest-agent
  • qemu-user-static 為所有 QEMU 支持的架構提供了一個帶用户模式和靜態連結模式的變種。 它的QEMU命令依照 qemu-target_architecture-static的規則命名, 例如, qemu-x86_64-static 代表目標架構為intel 64位CPU。
注意: 目前為止,Arch Linux 無論是在官方倉庫還是 AUR 倉庫中都不提供全系統模式且使用靜態連結的 QEMU 變種,原因是很少有人需要它們。

QEMU 的圖形前端[編輯 | 編輯原始碼]

與其他的虛擬化程序如 VirtualBoxVMware 不同, QEMU不提供管理虛擬機的GUI(運行虛擬機時出現的窗口除外),也不提供創建具有已保存設置的持久虛擬機的方法。除非您已創建自定義腳本以啟動虛擬機,否則必須在每次啟動時在命令行上指定運行虛擬機的所有參數。

Libvirt提供了一種管理 QEMU 虛擬機的便捷方式。有關可用的前端,請參閱 libvirt 客户端列表

創建新虛擬系統[編輯 | 編輯原始碼]

創建硬盤鏡像[編輯 | 編輯原始碼]

警吿: 本頁面的英文wiki中,對該節的準確性提出了懷疑,暫時停止該部分的翻譯,原頁面吿警如下: If I get the man page right the raw format only allocates the full size if the filesystem does not support "holes" or it is explicitly told to preallocate. See qemu-img(1) § NOTES. (Discuss in Talk:QEMU#)
提示:有關QEMU鏡像的更多信息,請參閱 QEMU Wikibook

除非直接從 CD-ROM 或網絡引導(並且不安裝系統到本地),運行 QEMU 時都需要硬盤鏡像。硬盤鏡像是一個文件,存儲虛擬機硬盤上的內容。

一個硬盤鏡像可能是 raw鏡像, 和客户機器上看到的內容一模一樣,並且將始終使用主機上的來賓硬盤驅動器的全部容量。此方法提供的I / O開銷最小,但可能會浪費大量空間,因為guest虛擬機上未使用的空間無法在主機上使用。

另外一種方式是qcow2 格式,僅當客户系統實際寫入內容的時候,才會分配鏡像空間。對客户機器來説,硬盤大小表現為完整大小,即使它可能僅佔用主機系統上的非常小的空間。此映像格式還支持QEMU快照功能(有關詳細信息,請參閱 #通過 monitor console 創建快照和管理快照)。但是,使用此格式而不是 raw 可能會影響性能。

QEMU 提供 qemu-img命令創建硬盤鏡像.例如創建一個 4 GiB raw 格式的鏡像:

$ qemu-img create -f raw image_file 4G

您也可以用 -f qcow2 創建一個 qcow2 鏡像。

ddfallocate 也可以創建一個 raw 鏡像。

注意: 您也可以通過 ddfallocate 創建一個所需大小的 raw 鏡像。
警吿: 如果硬盤鏡像存儲在 Btrfs 系統上,則應在創建任何映像之前考慮禁用該目錄的 寫時複製

覆寫(Overlay)鏡像[編輯 | 編輯原始碼]

你只需創建一個存儲鏡像(基礎(backing)鏡像),並讓 QEMU 在這個基礎鏡像的覆寫鏡像中做出改變。這允許你恢復到這個存儲鏡像的先前狀態。你可以通過在你想恢復的時候創建一個新的覆寫鏡像來進行恢復,這一切都是在基於原來的備份鏡像中進行。

要創建一個覆寫鏡像,執行下面的命令。

$ qemu-img create -o backing_file=img1.raw,backing_fmt=raw -f qcow2 img1.cow

之後,你可以正常運行 QEMU 虛擬機(參閱 #運行虛擬化的系統):

$ qemu-system-i386 img1.cow

然後,基礎鏡像將被保留,對該存儲的改變將被記錄在覆寫鏡像中。

當基礎鏡像的路徑改變時,需要進行修復。

警吿: 基礎鏡像的絕對文件系統路徑存儲在(二進制的)覆寫鏡像文件中。若改變基礎鏡像的路徑,可能需要做一些調整。

確保原來的基礎鏡像的路徑仍然指向該鏡像。如果有必要,在原路徑上做一個符號連結到新路徑上。然後執行如下命令:

$ qemu-img rebase -b /new/img1.raw /new/img1.cow

你也可以選擇執行一個 「不安全 」的重定向,即不檢查基礎鏡像的原路徑。

$ qemu-img rebase -u -b /new/img1.raw /new/img1.cow

調整鏡像大小[編輯 | 編輯原始碼]

警吿: 調整包含NTFS引導文件系統的鏡像將無法啟動已安裝的作業系統,推薦在操作之前進行備份

執行 qemu-imgresize 選項調整硬盤驅動鏡像的大小.它適用於 rawqcow2. 例如, 增加鏡像 10 GiB 大小, 運行:

$ qemu-img resize disk_image +10G

在磁盤映像擴容後,必須使用虛擬機內部系統的分區工具對該鏡像進行分區並格式化後才能真正開始使用新空間。

Shrinking an image[編輯 | 編輯原始碼]

When shrinking a disk image, you must first reduce the allocated file systems and partition sizes using the file system and partitioning tools inside the virtual machine and then shrink the disk image accordingly. For a Windows guest, this can be performed from the "create and format hard disk partitions" control panel.

警吿: Proceeding to shrink the disk image without reducing the guest partition sizes will result in data loss.

Then, to decrease image space by 10 GiB, run:

$ qemu-img resize --shrink disk_image -10G

Converting an image[編輯 | 編輯原始碼]

You can convert an image to other formats using qemu-img convert. This example shows how to convert a raw image to qcow2:

$ qemu-img convert -f raw -O qcow2 input.img output.qcow2

This will not remove the original input file.

準備安裝介質[編輯 | 編輯原始碼]

要將作業系統安裝到您的磁盤鏡像, 你需要作業系統的安裝介質 (例如 光盤, USB設備, 或 ISO 鏡像). 不要掛載安裝介質,因為 QEMU 要直接訪問媒體。

提示:如果使用光盤,最好先將媒體轉儲到文件中,因為這既可以提高性能,又不需要您直接訪問設備(也就是説,您可以將QEMU作為普通用户,而無需更改對媒體設備文件的訪問權限)。例如,如果CD-ROM設備節點名為/dev/cdrom,則可以使用以下命令將其轉儲到文件中:
$ dd if=/dev/cdrom of=cd_image.iso

安裝作業系統[編輯 | 編輯原始碼]

這是你第一次需要去啟動模擬器的步驟,為了在磁盤鏡像上安裝作業系統,你必須同時將磁盤鏡像與安裝介質裝載到虛擬機上,從安裝介質中啟動作業系統。

以i386的客户機為例,為了從CD-ROM內的把可用於啟動的ISO文件安裝到磁盤鏡像上,你需要:

$ qemu-system-x86_64 -cdrom iso_image -boot order=d -drive file=disk_image,format=raw

參閱 qemu(1) 獲得更多關於不同類型安裝介質的信息 (例如floppy,磁盤鏡像和物理驅動盤),參閱 #運行虛擬化的系統 了解更多有用的選項。

在安裝完作業系統後,就可以直接從QEMU鏡像內啟動了。(參閱 #運行虛擬化的系統

注意: 默認情況下僅分配給虛擬機128MiB的內存, 分配的內存大小可以通過 -m 調整, 比如 -m 512M-m 2G
提示:
  • 相較於指定 -boot order=x ,一部分用户感覺使用 -boot menu=on 啟用boot菜單的體驗更舒服些,至少在配置和實驗時是這樣的。
  • 當使用無界面(headless)模式時, 將會默認在本地5900端口啟動一個VNC伺服器, 可以用 TigerVNC 連接到客户機的系統上: vncviewer :5900
  • 若你在安裝過程中需要替換軟盤或CD,可以使用QEMU機器監視器(在虛擬機窗口中按Ctrl + Alt + 2)來刪除存儲設備並將其連接到虛擬機。使用 info block查看塊設備,然後使用change命令換出設備。按下 Ctrl + Alt + 1返回虛擬機。

運行虛擬化的系統[編輯 | 編輯原始碼]

qemu-system-* 程序 (例如 qemu-system-i386qemu-system-x86_64, 取決於客户機架構)用來運行虛擬化的客户機. 用法是:

$ qemu-system-i386 options disk_image

所有 qemu-system-*的選項是相同的,參見 qemu(1) 查看文檔和所有選項

Usually, if a option has many possible values, you can use

$ qemu-system-x86_64 option help

to list all possible values. If it supports properties, you can use

$ qemu-system-x86_64 option value,help

to list all available properties.

For example:

$ qemu-system-x86_64 -machine help
$ qemu-system-x86_64 -machine q35,help
$ qemu-system-x86_64 -device help
$ qemu-system-x86_64 -device qxl,help

You can use these methods and the qemu(1) documentationto to understand the options used in follow sections.

默認 QEMU 會在窗口中顯示虛擬機的視頻輸出.有一點要記住:當您單擊QEMU窗口,鼠標指針被捕獲。要放開,按 Ctrl+Alt+g.

警吿: QEMU 不應以 root 身份運行. 如果必須以 root 身份在某個腳本中運行 QEMU,那麼你需要使用 -runas 選項讓 QEMU 放棄root 權限

啟用 KVM[編輯 | 編輯原始碼]

KVM(基於內核的虛擬機)完全虛擬化必須要您的 Linux 內核和硬件支持,並且必須加載必要的內核模塊。更多信息參見 KVM

要在 KVM 模式中啟動 QEMU, 追加 -accel kvm 到啟動選項。檢查運行中的虛擬機是否啟用了 KVM,進入 QEMU 監視器,輸入 info kvm

注意:
  • -machine 選項中的 accel=kvm 參數與-enable-kvm-accel kvm 選項是等價的。
  • CPU模型 host 需要 KVM。
  • 如果你使用 GUI 工具去啟動 QEMU,但是性能體驗極差,那麼最好檢查一下是否真的開啟了 KVM 支持,因為 QEMU 可能選擇了備用的軟件級模擬。
  • 需要啟用 KVM 才能正常啟動 Windows 7 和 Windows8,否則會出現「藍屏」.

啟用 IOMMU (Intel VT-d/AMD-Vi)的支持[編輯 | 編輯原始碼]

首先,啟用 IOMMU。參閱 PCI passthrough via OVMF#Setting up IOMMU.

添加 -device intel-iommu 選項創建 IOMMU 設備:

$ qemu-system-x86_64 -enable-kvm -machine q35 -device intel-iommu -cpu host ..
注意: 在基於 Intel CPU 的系統上,用 -device intel-iommu 創建 QEMU 內的 IOMMU 設備將會禁用 PCI 直通, 並返回一個像這樣的錯誤報吿:
Device at bus pcie.0 addr 09.0 requires iommu notifier which is currently not supported by intel-iommu emulation
雖然仍然需要添加內核參數 intel_iommu=on 來重新映射 IO(例如,通過 vfio-pci 的 PCI 直通),但如果需要 PCI 直通,則不應設置 -device intel-iommu

Booting in UEFI mode[編輯 | 編輯原始碼]

The default firmware used by QEMU is SeaBIOS, which is a Legacy BIOS implementation. QEMU uses /usr/share/qemu/bios-256k.bin (provided by the seabios package) as a default read-only (ROM) image. You can use the -bios argument to select another firmware file. However, UEFI requires writable memory to work properly, so you need to emulate PC System Flash instead.

OVMF is a TianoCore project to enable UEFI support for Virtual Machines. It can be installed with the edk2-ovmf package.

There are two ways to use OVMF as a firmware. The first is to copy /usr/share/edk2-ovmf/x64/OVMF.fd, make it writable and use as a pflash drive:

-drive if=pflash,format=raw,file=/copy/of/OVMF.fd

All changes to the UEFI settings will be saved directly to this file.

Another and more preferable way is to split OVMF into two files. The first one will be read-only and store the firmware executable, and the second one will be used as a writable variable store. The advantage is that you can use the firmware file directly without copying, so it will be updated automatically by pacman.

Use /usr/share/edk2-ovmf/x64/OVMF_CODE.fd as a first read-only pflash drive. Copy /usr/share/edk2-ovmf/x64/OVMF_VARS.fd, make it writable and use as a second writable pflash drive:

-drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2-ovmf/x64/OVMF_CODE.fd \
-drive if=pflash,format=raw,file=/copy/of/OVMF_VARS.fd

If secure boot is wanted, replace /usr/share/edk2-ovmf/x64/OVMF_CODE.fd with /usr/share/edk2/x64/OVMF_CODE.secboot.fd.

Trusted Platform Module emulation[編輯 | 編輯原始碼]

QEMU can emulate Trusted Platform Module, which is required by some systems such as Windows 11.

Install the swtpm package, which provides a software TPM implementation. Create some directory for storing TPM data (/path/to/mytpm will be used as an example). Run this command to start the emulator:

$ swtpm socket --tpm2 --tpmstate dir=/path/to/mytpm --ctrl type=unixio,path=/path/to/mytpm/swtpm-sock

/path/to/mytpm/swtpm-sock will be created by swtpm: this is a UNIX socket to which QEMU will connect. You can put it in any directory.

By default, swtpm starts a TPM version 1.2 emulator. The --tpm2 option enables TPM 2.0 emulation.

Finally, add the following options to QEMU:

-chardev socket,id=chrtpm,path=/path/to/mytpm/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0

and TPM will be available inside the virtual machine. After shutting down the virtual machine, swtpm will be automatically terminated.

See the QEMU documentation for more information.

If guest OS still doesn't recognize the TPM device, try to adjust CPU Models and Topology options. It might cause problem.

宿主機和虛擬機數據交互[編輯 | 編輯原始碼]

網絡[編輯 | 編輯原始碼]

我們可以利用任何支持文件傳輸的網絡協議實現客户機和宿主機之間的數據交互, 例如 NFS, SMB, NBD, HTTP, FTP, 或 SSH, 當然這麼做的前提是你已經配置好二者之間的網絡,且在系統上啟動了相應的服務程序。

在默認情況下,用户模式的客户機能夠通過 10.0.2.2 這個IP訪問到宿主機。任何運行於宿主機上的服務端程序都可以通過這個地址被訪問到,比如説我們可以通過這個IP訪問到宿主機上的 SSH 伺服器或 SMB 伺服器。因此在這種情況下,客户機能夠掛載宿主機通過 SMBNFS 暴露出來的目錄,也可以訪問宿主機上的 HTTP 伺服器等。通常情況下宿主機無法訪問客户機上的服務,不過你也可以通過一些特殊的網絡配置達到這個目的 (參閱#Tap 網絡)

QEMU 端口轉發[編輯 | 編輯原始碼]

注意: QEMU's port forwarding is IPv4-only. IPv6 port forwarding is not implemented and the last patches were proposed in 2018.[1]

QEMU 能夠將宿主機的端口轉發到客户機上以實現一些功能,例如從宿主機上訪問客户機的 SSH 端口。

舉個例子,將宿主機上的 60022 端口與客户機上的22 (SSH) 端口進行綁定,需通過如下命令啟動 QEMU:

$ qemu-system-x86_64 disk_image -nic user,hostfwd=tcp::60022-:22

確認你客户機上的 sshd 程序正在運行,然後可以通過如下命令連接到客户機的 SSH 端口:

$ ssh guest-user@127.0.0.1 -p 60022

你可以用 SSHFS 把客户機的整個文件系統都掛到宿主機上,這樣就可以在宿主機上對客户機的文件系統進行讀寫了。

想進行多端口轉發的話, 只需要在 -nic 參數中指定多個 hostfwd, 以 VNC 端口為例:

$ qemu-system-x86_64 disk_image -nic user,hostfwd=tcp::60022-:22,hostfwd=tcp::5900-:5900

QEMU 的內置SMB伺服器[編輯 | 編輯原始碼]

QEMU的文檔中指出它有一個內置的 SMB 伺服器,但實際上,它只是在宿主機上加載一個自動生成的 smb.conf 配置文件 (位於/tmp/qemu-smb.random_string),然後啟動宿主機上的 Samba,使得客户機能夠通過一個IP位址進行訪問 (默認的IP位址是10.0.2.4)。這個方法只適用於用户網絡,在你不想在宿主機開啟通常的 Samba 服務 (客户機同樣能訪問這類Samba服務) 時這個方法還挺好用的。

選項 smb= 僅可以設置共享一個目錄,如果 QEMU 的 SMB 配置允許用户使用符號連結,那麼即使在虛擬機運行時也很容易新加入更多的目錄,只需要通過在共享目錄裡創建相應的軟連結就行。然而就算並沒有這麼配置,我們可以依照如下進行配置 SMB 伺服器

宿主機上必須安裝 Samba。通過如下QEMU命令啟用這項特性:

$ qemu-system-x86_64 -nic user,id=nic0,smb=shared_dir_path disk_image

shared_dir_path 就是你想要在宿主機和客户機之間共享的目錄。

接着,在客户機內,你應該能夠通過 10.0.2.4 訪問到名為 qemu 的共享文件夾,例如可以在 Windows 文件瀏覽器中前往 \\10.0.2.4\qemu 這個地址。

注意:
  • 如果你像這樣多次指定共享選項:-net user,smb=shared_dir_path1 -net user,smb=shared_dir_path2 或是 -net user,smb=shared_dir_path1,smb=shared_dir_path2,qemu 只會共享參數中最後的一個目錄。
  • 如果你不能訪問共享文件夾且客户機系統為 Windows, 請檢查 NetBIOS 協議是否被啟用[失效連結 2023-05-06 ⓘ] 並確認防火牆沒有屏蔽 NetBIOS 協議的 端口
  • 如果你無法訪問共享文件夾且客户機系統為 Windows 10 企業版/教育版或 Windows Server 2016, 請啟用遊客訪問.

共享多個文件夾並在運行時增刪文件夾的一個方法是:共享一個空目錄,然後在其中創建指向其餘共享目錄的符號連結。可以用下面的腳本修改SMB伺服器的配置,這個腳本還能使宿主機上不允許執行的文件在客户機內擁有執行權限。

#!/bin/sh
eval $(ps h -C smbd -o pid,args | grep /tmp/qemu-smb | gawk '{print "pid="$1";conf="$6}')
echo "[global]
allow insecure wide links = yes
[qemu]
follow symlinks = yes
wide links = yes
acl allow execute always = yes" >> "$conf"
# in case the change is not detected automatically:
smbcontrol --configfile="$conf" "$pid" reload-config

僅當 qemu 啟動的客户機第一次訪問到網絡磁盤後,才能應用該腳本。共享多文件夾的另一個方法是在配置文件裡加入額外的共享路徑,就像下面這樣

echo "[myshare]
path=another_path
read only=no
guest ok=yes
force user=username" >> $conf

這個共享文件夾可以在客户機內通過 \\10.0.2.4\myshare 訪問。

使用文件系統直通和 VirtFS[編輯 | 編輯原始碼]

參閱 QEMU 文檔.

Host file sharing with virtiofsd[編輯 | 編輯原始碼]

本文或本章節的語言、語法或風格需要改進。參考:Help:Style

virtiofsd is shipped with QEMU package. Documentation is available online[失效連結 2023-05-06 ⓘ] or /usr/share/doc/qemu/qemu/tools/virtiofsd.html on local file system with qemu-docs installed.

Add user that runs qemu to the 'kvm' user group, because it needs to access the virtiofsd socket. You might have to logout for change to take effect.

本文或本章節的事實準確性存在爭議。

原因: Running services as root is not secure. Also the process should be wrapped in a systemd service.(在 Talk:QEMU 中討論)


Start as virtiofsd as root:

# /usr/lib/virtiofsd --socket-path=/var/run/qemu-vm-001.sock --shared-dir /tmp/vm-001 --cache always

where

  • /var/run/qemu-vm-001.sock is a socket file,
  • /tmp/vm-001 is a shared directory between the host and the guest virtual machine.

The created socket file has root only access permission. Give group kvm access to it with:

# chgrp kvm qemu-vm-001.sock; chmod g+rxw qemu-vm-001.sock

Add the following configuration options when starting the virtual machine:

-object memory-backend-memfd,id=mem,size=4G,share=on \
-numa node,memdev=mem \
-chardev socket,id=char0,path=/var/run/qemu-vm-001.sock \
-device vhost-user-fs-pci,chardev=char0,tag=myfs

where

這篇文章的某些內容需要擴充。

原因: Explain the remaining options (or remove them if they are not necessary). (在 Talk:QEMU 中討論)
  • size=4G shall match size specified with -m 4G option,
  • /var/run/qemu-vm-001.sock points to socket file started earlier,

本文或本章節的語言、語法或風格需要改進。參考:Help:Style

原因:The section should not be specific to Windows.(在Talk:QEMU討論)

Remember, that guest must be configured to enable sharing. For Windows there are instructions. Once configured, Windows will have the Z: drive mapped automatically with shared directory content.

Your Windows 10 guest system is properly configured if it has:

  • VirtioFSSService windows service,
  • WinFsp.Launcher windows service,
  • VirtIO FS Device driver under "System devices" in Windows "Device Manager".

If the above installed and Z: drive is still not listed, try repairing "Virtio-win-guest-tools" in Windows Add/Remove programs.

在宿主機上掛載客户機的分區[編輯 | 編輯原始碼]

It can be useful to mount a drive image under the host system, it can be a way to transfer files in and out of the guest. This should be done when the virtual machine is not running.

The procedure to mount the drive on the host depends on the type of qemu image, raw or qcow2. We detail thereafter the steps to mount a drive in the two formats in #Mounting a partition from a raw image and #Mounting a partition from a qcow2 image. For the full documentation see Wikibooks:QEMU/Images#Mounting an image on the host.

警吿: 請確保重新運行虛擬機之前,所有掛載的分區都被卸載,否則很可能造成磁盤數據的損壞。

Mounting a partition from a raw image[編輯 | 編輯原始碼]

It is possible to mount partitions that are inside a raw disk image file by setting them up as loopback devices.

手動指出偏移量[編輯 | 編輯原始碼]

掛載磁盤鏡像中分區的一個方法是手動指定掛載的偏移量,你可以使用類似下面的命令完成這個操作:

# mount -o loop,offset=32256 disk_image mountpoint

offset=32256 選項實際上會被傳遞給 losetup 程序,用於設置一個起始地址為 32256 字節處的 loop 設備。接着這個 loop 設備將會被掛載。 你也可以使用 sizelimit 選項指定這個分區的具體大小,通常不需要指定該選項。

具體的偏移量取決於你的磁盤鏡像,你所需要的分區可能並不以 32256 字節處作為起始地址。運行 fdisk -l disk_image 查看磁盤鏡像中的分區,fdisk 會顯示分區的起始地址和結束地址,地址以 512 字節的扇區為單位,因此需要將該地址乘以 512 獲得可用於 mount 的字節偏移量。

loop模塊自動檢測分區[編輯 | 編輯原始碼]

Linux 的 loop 驅動支持 loopback 設備的分區,不過默認情況下它是關閉的,可以通過下面的方法啟用:

  • 卸載所有 loopback 設備 (比如説卸載所有掛載的鏡像)。
  • 卸下 loop 內核模塊, 接着以 max_part=15 參數重新加載該模塊。 此外,你可以用 max_loop 參數設置 loop 設備的最大數量。
提示:你可以在 /etc/modprobe.d 增加一個條目使得每次加載 loop 模塊時帶上 max_part=15 參數, 或者把 loop.max_part=15 加入內核命令行, 這得看你的內核是否帶有 loop.ko 模塊。

將鏡像文件設置為 loopback 設備:

# losetup -f -P disk_image

接着,假設創建的loop設備名稱為 /dev/loop0 ,相應的 /dev/loop0pX 也會被自動創建, X 代表分區的編號,這些分區可以被直接掛載,例如:

# mount /dev/loop0p1 mountpoint

如要使用 udisksctl 掛載磁盤鏡像, 參閱 Udisks#Mount loop devices.

使用 kpartx[編輯 | 編輯原始碼]

multipath-tools 包內的 kpartx 可以讀取設備的分區表,然後為每個分區創建一個新設備,舉個例子:

# kpartx -a disk_image

這條命令將會為你設置 loopback 設備,並在 /dev/mapper/ 下創建必要的分區設備。

掛載 qcow2 鏡像內的分區[編輯 | 編輯原始碼]

我們將使用 qemu-nbd 完成這一功能, 同時它也能讓我們使用 NBD (network block device) 協議共享該磁盤鏡像。

首先,我們需要加載 nbd 模塊:

# modprobe nbd max_part=16

接着,共享該磁盤並創建設備條目:

# qemu-nbd -c /dev/nbd0 /path/to/image.qcow2

進行分區發現檢測:

# partprobe /dev/nbd0

fdisk 可以獲取 nbd0 內各分區的相關信息:

# fdisk -l /dev/nbd0
Disk /dev/nbd0: 25.2 GiB, 27074281472 bytes, 52879456 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xa6a4d542

Device      Boot   Start      End  Sectors  Size Id Type
/dev/nbd0p1 *       2048  1026047  1024000  500M  7 HPFS/NTFS/exFAT
/dev/nbd0p2      1026048 52877311 51851264 24.7G  7 HPFS/NTFS/exFAT

接下來可以掛載鏡像的任意分區了,比如説我們要掛載分區2:

# mount /dev/nbd0p2 mountpoint

完成任務後,切記卸載鏡像文件,然後根據之前的操作一步步還原,即分區並斷開與 nbd 設備的連接:

# umount mountpoint
# qemu-nbd -d /dev/nbd0

將任意分區作為磁盤鏡像唯一主分區[編輯 | 編輯原始碼]

有時,你可能想在 QEMU 中使用物理機的一個系統分區。在虛擬機裡使用原始分區可以改善讀寫性能,因為此時 QEMU 不需要經過宿主機的文件系統層完成讀寫操作,該分區同樣可以用於在宿主機和客户機之間進行數據共享。

在 Arch Linux 的默認設置中,代表原始分區的設備文件的所有者為 root , 隸屬於 disk 組。如果你希望使用一個非 root 用户能夠對原始分區進行讀寫,那麼請更改對應設備文件的所有者為該用户,將這個用户加入 disk 組中,或者使用 ACL 完成更精細的權限管理。

警吿:
  • 不推薦讓虛擬機修改宿主機系統上重要數據,比如説對 root 分區進行修改,儘管你擁有這麼做的能力。
  • 不要同時掛載一塊在宿主機和客户機內都可讀寫的分區,否則會造成數據的損壞。

在完成上述設置後,你可以將該分區作為一塊虛擬磁盤添加到 QEMU 虛擬機內了。

然而,如果你想使得整個虛擬機都包含在單個分區中,事情就開始變得有些複雜了。在這個場景下,由於系統分區本身是作為文件系統完成格式化的,而非一個帶有 MBR 的分區設備,我們便無法在這個分區上安裝引導加載程序,進而也就沒有辦法啟動虛擬機了。要啟動這類虛擬機,你有如下幾種選擇:#手動指定 kernel 和 initrd#模擬一塊帶 MBR 的磁盤#使用設備映射器#使用線性 RAID或是#使用網絡塊設備

手動指定 kernel 和 initrd[編輯 | 編輯原始碼]

QEMU 支持直接加載 Linux 內核init ramdisks,從而繞過了類似 GRUB 這類的引導加載程序。它會把包含根文件系統的物理分區作為虛擬機的虛擬磁盤,然後啟動虛擬機。通過類似下面的命令可以完成這些操作:

注意: 在示例中, 我們使用的是 宿主機的 鏡像,而非客户機的。如果你希望使用客户機的鏡像,請將 /dev/sda3 設置為只讀(為了保護宿主機上的文件系統),並且指定 /full/path/to/images ,或者在客户機內使用一些 kexec 的技巧,重新加載客户機的內核(會延長啟動時間)
$ qemu-system-x86_64 -kernel /boot/vmlinuz-linux -initrd /boot/initramfs-linux.img -append root=/dev/sda /dev/sda3

在上面這個例子中,宿主機上的 /dev/sda3 物理分區被用於客户機的根文件系統,但是在虛擬機內部它的名字則是 /dev/sda

當然你可以指定任意一個 kernel 和 initrd,而不局限於Arch Linux提供的。

-append 中可以傳遞許多 內核參數, 需要用單引號或雙引號將他們包起來,比如:

... -append 'root=/dev/sda1 console=ttyS0'

模擬一塊帶 MBR 的磁盤[編輯 | 編輯原始碼]

當我們想要既保持物理分區遵循文件系統的格式,又作為客户機的虛擬磁盤包含客户機內的分區時,我們有一個比較複雜的方法,那就是模擬一塊帶 MBR 的磁盤,這樣就使得它可以被類似 GRUB 的引導程序正常啟動。

假設你有一塊普通的、未掛載的硬盤分區 /dev/hdaN ,分區內有些文件系統,若想將其製作為QEMU硬盤鏡像,需要在該物理分區內動態地預置一個主引導記錄(MBR)。更寬泛地説,該分區可以是更大的模擬磁盤中的一部分,尤其是那種模擬了物理磁盤,但僅向虛擬機暴露 /dev/hdaN 名稱的塊設備。

這類虛擬磁盤可以用帶引用的 VMDK 文件形容,VMDK內的引用指向 MBR 的副本以及實際的分區。 但 QEMU 並不支持這類VMDK格式,例如通過如下命令創建的虛擬機:

$ VBoxManage internalcommands createrawvmdk -filename /path/to/file.vmdk -rawdisk /dev/hda

將會被QEMU拒絕,並返回一個錯誤信息

Unsupported image type 'partitionedDevice'

注意 VBoxManage 會創建兩個文件:file.vmdkfile-pt.vmdk, 後一個是 file.vmdk MBR 的副本。對目標分區外的數據或MBR本身的讀操作將會返回0, 而寫操作則會被丟棄。

使用設備映射器[編輯 | 編輯原始碼]

與使用 VMDK 描述文件類似的方法就是使用設備映射器,設備映射器會在目標分區內添加一份帶有 loop 設備的 MBR 文件。在此種情況下,不要求虛擬磁盤與原始分區擁有同樣的大小。首先創建一個包含 MBR 的文件:

$ dd if=/dev/zero of=/path/to/mbr count=2048

在這裏,我們通過這個命令,使用現代化的磁盤分區程序創建了一個符合分區對齊策略的文件,總共大小為 1MiB(2048 * 512 字節)。為了兼容老式的磁盤分區程序,可能要求其為 63 個扇區而非 2048 個扇區。MBR 表僅佔一塊512位元組的塊,剩餘的空間可以用於創建一個 BIOS 啟動分區,或者在創建一個在混合分區方案中需要用到的 GUID 分區表。接着我們將 loop 設備附加到 MBR 文件上:

# losetup --show -f /path/to/mbr
/dev/loop0

在這個例子裏,最終生成的設備為 /dev/loop0,設備映射器將會把 MBR 文件與分區結合起來:

# echo "0 2048 linear /dev/loop0 0
2048 `blockdev --getsz /dev/hdaN` linear /dev/hdaN 0" | dmsetup create qemu

生成的 /dev/mapper/qemu 可以被作為 QEMU 原生鏡像使用了,在虛擬磁盤上創建一個分區表(可參閱關於線性 RAID 的部分),以及相應的引導加載器代碼(代碼會存放在 /path/to/mbr)需要額外的步驟。

下面的步驟中,/dev/hdaN 在虛擬磁盤和物理磁盤上的位置都相同,並且除了 MBR(副本)外磁盤的其餘部分都是隱藏的:

# dd if=/dev/hda count=1 of=/path/to/mbr
# loop=`losetup --show -f /path/to/mbr`
# start=`blockdev --report /dev/hdaN | tail -1 | awk '{print $5}'`
# size=`blockdev --getsz /dev/hdaN`
# disksize=`blockdev --getsz /dev/hda`
# echo "0 1 linear $loop 0
1 $((start-1)) zero
$start $size linear /dev/hdaN 0
$((start+size)) $((disksize-start-size)) zero" | dmsetup create qemu

通過管道傳入作為 dmsetup 標準輸入的是一張表,該表的格式與 VBoxManage 創建的VMDK描述文件中的表格式相同, 即我們同樣能通過 dmsetup create qemu --table table_file 加載VMDK描述文件中的表。 對於虛擬機來説, 僅 /dev/hdaN 能被訪問, 而對其餘部分, 除了第一個扇區外,對其他扇區的讀操作都只會返回0, 寫操作都會被丟棄。 可以用 dmsetup table qemu 顯示 /dev/mapper/qemu 的表(用 udevadm info -rq name /sys/dev/block/major:minormajor:minor 轉化為類似 /dev/blockdevice 的名字)。若要刪除創建的設備,請使用 dmsetup remove qemulosetup -d $loop

設備映射器方法一個可能的應用場景與Windows XP有關,比如説要在Windows XP安裝中進行多引導配置,並且有可能要採用混合分區方案(從物理硬件上説,Windows XP可能是唯一使用MBR分區表的系統,更現代化的作業系統能使用GUID分區表)。Windows XP支持硬件配置文件,因此同樣的安裝可以選擇不同的硬件配置完成(在本例中是裸機與虛擬機),而Windows僅需為每個配置文件安裝一次新檢測到的硬件的驅動即可。注意在這個例子裏, 要更新MBR副本中bootloader代碼的部分,使得它直接從 /dev/hdaN 加載Windows XP而不是系統內自帶的多引導bootloader(比如GRUB)。或者,將包含bootloader安裝的啟動分區之副本包含於虛擬磁盤中,同樣也可起到類似MBR的作用。

使用線性 RAID[編輯 | 編輯原始碼]

本文內容或本節內容已經過期。

原因: CHS has been obsolete for decades. (在Talk:QEMU討論)

你同樣能用 線性模式(需要 linear.ko 內核驅動)的RAID以及一塊loop設備完成這件事。

首先創建一個用於容納MBR的小文件:

$ dd if=/dev/zero of=/path/to/mbr count=32

這樣就創建了一個 16 KiB(32 * 512位元組)的小文件。該文件最好不要太小(儘管 MBR 只需要一個512位元組大小的塊),過小的話將會限制軟 RAID 設備的 chunk 大小,對於性能是有影響的。將 loop 設備設置到 MBR 文件上。

# losetup -f /path/to/mbr

因為我們尚無法使用其他 loop 設備, 因此就先假設產生的設備名為 /dev/loop0。下一步將創建合併式 MBR + 使用軟件 RAID 的磁盤鏡像 /dev/hdaN

# modprobe linear
# mdadm --build --verbose /dev/md0 --chunk=16 --level=linear --raid-devices=2 /dev/loop0 /dev/hdaN

這一步產生的 /dev/md0 設備將在之後作為一個 QEMU 原始鏡像(別忘了給模擬器相應的訪問權限)。最後一步(也是比較取巧的一步)是設置磁盤配置,使得 MBR 內主分區的起始地址與 /dev/md0 中某一塊 /dev/hdaN 的起始地址(在這個例子中是 16 * 512 = 16384 字節的偏移處)。請在宿主機上用 fdisk 完成該操作,別在虛擬機裏面這麼做,因為默認的 QEMU 內的磁盤檢測程序常給出無法進行千位捨入的偏移量(比如 31.5 KiB),軟件RAID無法處理這樣的情況。因此請在主機上進行下面的操作:

# fdisk /dev/md0

按下 X 進入專家選單, 設置每個磁道上 's'ectors 的數目,使得一個柱面的大小與MBR文件中相符。對於雙磁頭柱面,且每個扇區為 512 字節的情況, 每個磁道上的扇區數當為 16, 因此我們通過計算 2x16x512=16k 得到柱面的大小。

按下 R 返回主界面。

按下 P 並檢查柱面大小為 16k。

現在,來創建與 /dev/hdaN 對應的主分區。 設置它的起始地址為柱面2, 結束地址在磁盤的末端(注意現在的柱面編號已經與進入 fdisk 時的編號不同了)。

最後,把結果寫入:完成~ 現在你擁有了一塊可以直接從宿主機進行掛載的分區,該分區同樣也是 QEMU 磁盤鏡像的一部分。

$ qemu-system-x86_64 -hdc /dev/md0 [...]

現在,若原始的 /dev/hdaN 分區中包含必要的一些工具,你就可以安全地用 QEMU 在磁盤鏡像上設置任何一個引導加載程序。

使用網絡塊設備[編輯 | 編輯原始碼]

With Network Block Device, Linux can use a remote server as one of its block device. 你也可以用 nbd-server(在 nbd 包中)為 QEMU 創建一個 MBR 封裝器。

假設你已經用上面所説的方法創建了一個方法創建了一個MBR封裝文件,將其重命名為 wrapper.img.0。然後在同一個目錄下創建一個名為 wrapper.img.1的符號連結,指向你選擇的分區。然後,還是在這個文件夾下,創建如下的腳本:

#!/bin/sh
dir="$(realpath "$(dirname "$0")")"
cat >wrapper.conf <<EOF
[generic]
allowlist = true
listenaddr = 127.713705
port = 10809

[wrap]
exportname = $dir/wrapper.img
multifile = true
EOF

nbd-server \
    -C wrapper.conf \
    -p wrapper.pid \
    "$@"

.0 and .1 這兩個後綴名是關鍵,名字的其他其他部分都可以更改。在運行上面的腳本(有可能需要以root身份運行,保證nbd-server能夠去訪問該分區)後,你可以用如下命令啟動QEMU:

qemu-system-x86_64 -drive file=nbd:127.713705:10809:exportname=wrap [...]

Using an entire physical disk device inside the virtual machine[編輯 | 編輯原始碼]

本文或本章節的語言、語法或風格需要改進。參考:Help:Style

原因:Duplicates #Using any real partition as the single primary partition of a hard disk image, libvirt instructions do not belong to this page.(在Talk:QEMU討論)

You may have a second disk with a different OS (like Windows) on it and may want to gain the ability to also boot it inside a virtual machine. Since the disk access is raw, the disk will perform quite well inside the virtual machine.

Windows virtual machine boot prerequisites[編輯 | 編輯原始碼]

Be sure to install the virtio drivers inside the OS on that disk before trying to boot it in the virtual machine. For Win 7 use version 0.1.173-4. Some singular drivers from newer virtio builds may be used on Win 7 but you will have to install them manually via device manager. For Win 10 you can use the latest virtio build.

Set up the windows disk interface drivers[編輯 | 編輯原始碼]

You may get a 0x0000007B bluescreen when trying to boot the virtual machine. This means Windows can not access the drive during the early boot stage because the disk interface driver it would need for that is not loaded / is set to start manually.

The solution is to enable these drivers to start at boot.

In HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services, find the folders aliide, amdide, atapi, cmdide, iastor (may not exist), iastorV, intelide, LSI_SAS, msahci, pciide and viaide. Inside each of those, set all their "start" values to 0 in order to enable them at boot. If your drive is a PCIe NVMe drive, also enable that driver (should it exist).

Find the unique path of your disk[編輯 | 編輯原始碼]

Run ls /dev/disk/by-id/: tere you pick out the ID of the drive you want to insert into the virtual machine, for example ata-TS512GMTS930L_C199211383. Now add that ID to /dev/disk/by-id/ so you get /dev/disk/by-id/ata-TS512GMTS930L_C199211383. That is the unique path to that disk.

Add the disk in QEMU CLI[編輯 | 編輯原始碼]

In QEMU CLI that would probably be:

-drive file=/dev/disk/by-id/ata-TS512GMTS930L_C199211383,format=raw,media=disk

Just modify file= to be the unique path of your drive.

Add the disk in libvirt[編輯 | 編輯原始碼]

In libvirt XML that translates to

$ virsh edit vmname
...
    <disk type="block" device="disk">
      <driver name="qemu" type="raw" cache="none" io="native"/>
      <source dev="/dev/disk/by-id/ata-TS512GMTS930L_C199211383"/>
      <target dev="sda" bus="sata"/>
      <address type="drive" controller="0" bus="0" target="0" unit="0"/>
    </disk>
...

Just modify "source dev" to be the unique path of your drive.

Add the disk in virt-manager[編輯 | 編輯原始碼]

When creating a virtual machine, select "import existing drive" and just paste that unique path. If you already have the virtual machine, add a device, storage, then select or create custom storage. Now paste the unique path.

網絡[編輯 | 編輯原始碼]

警吿: 本部分在翻譯過程中,英文wiki產生style吿警,這代表日後本節的內容將會有相應調整,暫停本節的翻譯: 網絡拓撲 (#僅主機 網絡, #內部網絡 節中以及其他節中引用的部分) 不應當根據不同的虛擬網絡接口實現進行劃分和描述, 例如#用户模式, #Tap 網絡, #通過 VDE2 配置網絡

採用TAP設備和網橋的虛擬網絡的性能應該會比使用用户模式網絡或VDE要好,原因在於TAP設備和網橋是在內核中實現的。

此外,虛擬網絡的性能可以通過將 virtio 網絡設備直接註冊到虛擬機中改善,這比默認情況下模擬 e1000 NIC的性能表現要更好,參閱 #安裝 virtio 驅動 獲得更多相關信息。

關於鏈路層地址的限制[編輯 | 編輯原始碼]

若在QEMU啟動中指定了 -net nic 參數,QEMU將會為虛擬機註冊一塊虛擬網卡,其鏈路層地址為 52:54:00:12:34:56 。然而,當在多台虛擬機之間搭建橋接網絡時,每台虛擬機在tap設備的虛擬機端都需要擁有一個獨一無二的鏈路層地址 (MAC),否則網橋會因為收到多個不同源卻擁有相同MAC地址的數據包而無法正常工作。即使你為多個tap設備配置了不同的MAC地址也依舊會出現這個問題,因為當數據包通過tap設備時,tap設備並不會改寫包內的鏈路層地址。

因此請確保每個虛擬機擁有自己獨一無二的網卡地址, 並且它們都以 52:54: 開頭。 可以通過如下命令手動設置虛擬機的MAC地址, 下面的'X'可以替換成任何16進制字符:

$ qemu-system-x86_64 -net nic,macaddr=52:54:XX:XX:XX:XX -net vde disk_image

生成不同的鏈路層地址有很多方法:

  • 手動為每個NIC設置獨一無二的鏈路層地址,這麼做的優點在於每次啟動虛擬機時,DHCP伺服器都會將相同的IP位址分配給對應的MAC地址,但是這個方法在需要大量虛擬機的情況下就不適用了。
  • 在每次啟動虛擬機時隨機生成鏈路層地址,實際情況下地址衝突的概率可視為0, 不過此方法的缺點在於DHCP伺服器每次都會分配一個不同的IP位址。你可以用如下的這些腳本生成隨機的鏈路層地址,並用於 macaddr 參數中。
printf -v macaddr "52:54:%02x:%02x:%02x:%02x" $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff ))
qemu-system-x86_64 -net nic,macaddr="$macaddr" -net vde disk_image
  • 使用這個腳本 qemu-mac-hasher.py 可以根據虛擬機的名字進行Hash得到一個鏈路層地址。 只要每台虛擬機的名字是獨一無二的, 這個方法就結合了上述兩種方法的優點: 每次運行腳本生成的鏈路層地址都是相同的, 且衝突概率在實際應用中仍可視為0.
qemu-mac-hasher.py
#!/usr/bin/env python
# usage: qemu-mac-hasher.py <VMName>

import sys
import zlib

crc = str(hex(zlib.crc32(sys.argv[1].encode("utf-8")))).replace("x", "")[-8:]
print("52:54:%s%s:%s%s:%s%s:%s%s" % tuple(crc))

如果要在腳本調用這個方法,你可以參照下面的例子:

vm_name="VM Name"
qemu-system-x86_64 -name "$vm_name" -net nic,macaddr=$(qemu-mac-hasher.py "$vm_name") -net vde disk_image

用户模式[編輯 | 編輯原始碼]

默認情況下,沒有任何-netdev參數,QEMU將使用帶有內置DHCP伺服器的用户模式網絡。當您的虛擬機運行其DHCP客户端時,將為其分配IP位址,它們將能夠通過QEMU偽裝的IP來訪問物理主機的網絡。

注意: ICMPv6 尚未完成實現,因此不會起效:Slirp: external icmpv6 not supported yet. Pinging an IPv6 address will not work.

如果主機已連接Internet,則此默認配置可以使您的虛擬機輕鬆訪問Internet。但是如果您同時啟動多個虛擬機,則虛擬機將無法在外部網絡上直接看到,虛擬機也將無法相互通信。

QEMU的用户模式網絡可以提供更多功能,例如內置TFTP或SMB伺服器,將主機端口重定向到虛擬機(例如,允許SSH連接到虛擬機)或將虛擬機連接到VLAN,以便它們可以彼此通信。 有關更多詳細信息,請參見-net user標誌上的QEMU文檔。

但是,用户模式網絡在效用和性能上都有局限性。更高級的網絡配置需要使用TAP設備或其他方法。

注意: 如果主機系統使用systemd-networkd,請確保按照systemd-networkd#Required services and setup中的描述對/etc/resolv.conf文件進行符號連結,否則虛擬機系統中的DNS查找將無法進行。
提示:To use the virtio driver with user-mode networking, the option is: -nic user,model=virtio-net-pci.

Tap 網絡[編輯 | 編輯原始碼]

Tap devices是一個Linux內核特性,允許您創建作為真實網絡接口的虛擬網絡接口。發送到tap接口的包將被傳遞到一個用户空間程序(如QEMU),該程序將自己綁定到該接口。

QEMU可以為虛擬機使用tap網絡,因此發送到tap接口的包將被發送到虛擬機,並顯示為來自虛擬機中的網絡接口(通常是以太網接口)。相反,虛擬機通過其網絡接口發送的所有內容都將出現在tap接口上。

Linux橋接驅動程序支持Tap設備,因此可以將Tap設備彼此橋接在一起,也可以連接其他主機接口,如eth0。如果您希望您的虛擬機能夠相互通信,或者希望LAN上的其他機器能夠與虛擬機通信,那麼這是非常理想的方案。

警吿: 如果您將tap設備和一些主機接口橋接在一起,例如eth0,您的虛擬機將直接出現在外部網絡上,這將使它們遭受攻擊的可能。根據您的虛擬機可以訪問的資源,您可能需要採取所有precautions來保護您的虛擬機。如果風險太大,虛擬機沒有資源或您設置多個虛擬機,一個更好的解決方案可能是使用host-only networking建立NAT。在這種情況下,您只需要在主機上安裝一個防火牆,而不是為每個虛擬機安裝多個防火牆。

正如在用户模式網絡部分中指出的,tap設備提供比用户模式具有更高的網絡性能。如果虛擬機中的作業系統支持virtio網絡驅動程序,那麼網絡性能也會顯著提高。假設使用tap0設備,virtio驅動程序在客户端上使用,並且沒有使用腳本來幫助啟動/停止網絡,使用下面的qemu命令:

-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no

但是,如果已經使用帶有virtio網絡驅動程序的Tap設備,則甚至可以通過啟用vhost來提高網絡性能,例如:

-device virtio-net,netdev=network0 -netdev tap,id=network0,ifname=tap0,script=no,downscript=no,vhost=on

詳情請參考:https://web.archive.org/web/20160222161955/http://www.linux-kvm.com:80/content/how-maximize-virtio-net-performance-vhost-net

僅主機 網絡[編輯 | 編輯原始碼]

如果為網橋提供了IP位址,並且使能發往該網橋的流量允許,但沒有實際接口(例如eth0)連接到網橋,則虛擬機與虛擬機間,虛擬機與主機間能夠相互通信。但是,如果您沒有在物理主機上設置IP掩蔽,則他們將無法與外部網絡進行通信。 此配置被其他虛擬化軟件(例如VirtualBox)稱為「僅主機網絡模式」。

提示:
  • 如果你想設置IP掩蔽,例如虛擬機的NAT,請查看Internet sharing#Enable NAT頁面。
  • 您也許想在網橋接口上運行一個DHCP伺服器來服務虛擬網絡。例如,使用172.20.0.1/16子網,dnsmasq作為DHCP伺服器:
# ip addr add 172.20.0.1/16 dev br0
# ip link set br0 up
# dnsmasq --interface=br0 --bind-interfaces --dhcp-range=172.20.0.2,172.20.255.254

內部網絡[編輯 | 編輯原始碼]

如果您不為網橋提供IP位址並在iptables添加INPUT規則鏈,將所有流向網橋中的數據丟棄,則虛擬機將能夠彼此通信,但無法與物理主機或外部網絡通信。此配置被其他虛擬化軟件(例如VirtualBox)稱為「內部網絡」。您將需要為虛擬機分配靜態IP位址,或在其中一個虛擬機上運行DHCP伺服器。

在默認情況下,iptables將丟棄橋接網絡中的數據包。您可能需要使用這樣的iptables規則來允許橋接網絡中的數據包:

# iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT

使用 qemu-bridge-helper 橋接網絡[編輯 | 編輯原始碼]

這種方法不需要啟動腳本,並且很容易適應多個tap和多個橋。它使用/usr/lib/qemu/qemu-bridge-helper,允許在現有橋上創建tap設備。

提示:

首先,創建一個配置文件,包含QEMU使用的所有網橋的名稱:

/etc/qemu/bridge.conf
allow br0
allow br1
...

Make sure /etc/qemu/ has 755 permissions. QEMU issues and GNS3 issues may arise if this is not the case.

Now start the virtual machine; the most basic usage to run QEMU with the default network helper and default bridge br0:

$ qemu-system-x86_64 -nic bridge [...]

Using the bridge br1 and the virtio driver:

$ qemu-system-x86_64 -nic bridge,br=br1,model=virtio-net-pci [...]

手工創建網橋[編輯 | 編輯原始碼]

本文或本章節的語言、語法或風格需要改進。參考:Help:Style

原因:This section needs serious cleanup and may contain out-of-date information.(在Talk:QEMU討論)
提示:自 QEMU 1.1 起,network bridge helper可以為您設置 tun/tap,而無需其他腳本。 請參閱#使用 qemu-bridge-helper 橋接網絡

下面介紹如何將虛擬機連接到主機接口,如eth0,這可能是最常見的配置。這種配置使虛擬機看起來直接位於外部網絡,與物理主機位於同一以太網段。

我們將用橋適配器替換普通的以太網適配器,然後將普通的以太網適配器綁定到它。

  • 啟用 IPv4 轉發:
# sysctl -w net.ipv4.ip_forward=1

要使更改永久生效,請將 /etc/sysctl.d/99-sysctl.conf 中的 net.ipv4.ip_forward = 0 更改為 net.ipv4.ip_forward = 1

  • 加載 tun 模塊,並將其配置為在引導時加載。詳見Kernel modules
  • 現在創建橋。有關詳細信息,請參見Bridge with netctl。請記住網橋的命名,如 br0,或將以下腳本更改為網橋的名稱。In the run-qemu script below, br0 is set up if not listed, as it is assumed that by default the host is not accessing network via the bridge.
  • 創建 QEMU 用於打開 tap 適配器的腳本,該腳本具有 root:kvm 750權限:
/etc/qemu-ifup
#!/bin/sh

echo "Executing /etc/qemu-ifup"
echo "Bringing up $1 for bridged mode..."
sudo /usr/bin/ip link set $1 up promisc on
echo "Adding $1 to br0..."
sudo /usr/bin/brctl addif br0 $1
sleep 2
  • 創建QEMU用於在/etc/qemu-ifdown中關閉tap適配器的腳本,該腳本具有root:kvm 750權限:
/etc/qemu-ifdown
#!/bin/sh

echo "Executing /etc/qemu-ifdown"
sudo /usr/bin/ip link set $1 down
sudo /usr/bin/brctl delif br0 $1
sudo /usr/bin/ip link delete dev $1
  • 使用 visudo 將以下內容添加到 sudoers 文件中:
Cmnd_Alias      QEMU=/usr/bin/ip,/usr/bin/modprobe,/usr/bin/brctl
%kvm     ALL=NOPASSWD: QEMU
  • 您可以使用以下 run-qemu 腳本啟動QEMU:
run-qemu
#!/bin/bash
: '
e.g. with img created via:
qemu-img create -f qcow2 example.img 90G
run-qemu -cdrom archlinux-x86_64.iso -boot order=d -drive file=example.img,format=qcow2 -m 4G -enable-kvm -cpu host -smp 4
run-qemu -drive file=example.img,format=qcow2 -m 4G -enable-kvm -cpu host -smp 4
'

nicbr0() {
    sudo ip link set dev $1 promisc on up &> /dev/null
    sudo ip addr flush dev $1 scope host &>/dev/null
    sudo ip addr flush dev $1 scope site &>/dev/null
    sudo ip addr flush dev $1 scope global &>/dev/null
    sudo ip link set dev $1 master br0 &> /dev/null
}
_nicbr0() {
    sudo ip link set $1 promisc off down &> /dev/null
    sudo ip link set dev $1 nomaster &> /dev/null
}

HASBR0="$( ip link show | grep br0 )"
if [ -z $HASBR0 ] ; then
    ROUTER="192.168.1.1"
    SUBNET="192.168.1."
    NIC=$(ip link show | grep en | grep 'state UP' | head -n 1 | cut -d":" -f 2 | xargs)
    IPADDR=$(ip addr show | grep -o "inet $SUBNET\([0-9]*\)" | cut -d ' ' -f2)
    sudo ip link add name br0 type bridge &> /dev/null
    sudo ip link set dev br0 up
    sudo ip addr add $IPADDR/24 brd + dev br0
    sudo ip route del default &> /dev/null
    sudo ip route add default via $ROUTER dev br0 onlink
    nicbr0 $NIC
    sudo iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT
fi

USERID=$(whoami)
precreationg=$(ip tuntap list | cut -d: -f1 | sort)
sudo ip tuntap add user $USERID mode tap
postcreation=$(ip tuntap list | cut -d: -f1 | sort)
TAP=$(comm -13 <(echo "$precreationg") <(echo "$postcreation"))
nicbr0 $TAP

printf -v MACADDR "52:54:%02x:%02x:%02x:%02x" $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff ))
qemu-system-x86_64 -net nic,macaddr=$MACADDR,model=virtio \
    -net tap,ifname=$TAP,script=no,downscript=no,vhost=on \
    $@

_nicbr0 $TAP
sudo ip link set dev $TAP down &> /dev/null
sudo ip tuntap del $TAP mode tap

if [ -z $HASBR0 ] ; then
    _nicbr0 $NIC
    sudo ip addr del dev br0 $IPADDR/24 &> /dev/null
    sudo ip link set dev br0 down
    sudo ip link delete br0 type bridge &> /dev/null
    sudo ip route del default &> /dev/null
    sudo ip link set dev $NIC up
    sudo ip route add default via $ROUTER dev $NIC onlink &> /dev/null
fi

然後,要啟動VM,可以這樣做:

$ run-qemu -hda myvm.img -m 512
/etc/sysctl.d/10-disable-firewall-on-bridge.conf
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

In order to apply the parameters described above on boot, you will also need to load the br-netfilter module on boot. Otherwise, the parameters will not exist when sysctl will try to modify them.

/etc/modules-load.d/br_netfilter.conf
br_netfilter

運行 sysctl -p /etc/sysctl.d/10-disable-firewall-on-bridge.conf 立即應用更改。

參見 libvirt wikiFedora bug 512206。如果在引導過程中 sysctl 報出關於不存在文件的錯誤,請在引導時加載 bridge 模塊。參見Kernel module#systemd

或者,您可以配置 iptables,通過添加類似這樣的規則,允許所有流量通過橋進行轉發:

-I FORWARD -m physdev --physdev-is-bridged -j ACCEPT

物理設備和 Tap 設備之間通過 iptables 進行網絡共享[編輯 | 編輯原始碼]

本文或本章節可能需要合併到Internet_sharing

附註: Duplication, not specific to QEMU.(在 Talk:QEMU 中討論)

橋接網絡能在有線接口(例如eth0)之間工作,並且很容易設置。但是,如果主機通過無線設備連接到網絡,則無法進行橋接。

參見 Network bridge#Wireless interface on a bridge

解決這個問題的一種方法是,給tap設備設置一個靜態IP,使linux自動處理它的路由,然後通過iptables規則轉發tap接口和連接到網絡的設備之間的通信。

參見 Internet sharing.

在那裏你可以找到在設備之間共享網絡所需要的東西,包括tap和tun。下面將進一步介紹所需的一些主機配置。如上所述,需要為靜態IP配置客户機,使用分配給tap接口的IP作為網關。需要注意的是,如果客户機上的DNS伺服器在從一個連接到網絡的主機設備切換到另一個時發生了更改,那麼它們可能需要手動編輯。

要在每次啟動時允許 IP 轉發,需要在 /etc/sysctl.d 中,向 sysctl 配置文件添加以下信息:

net.ipv4.ip_forward = 1
net.ipv6.conf.default.forwarding = 1
net.ipv6.conf.all.forwarding = 1

iptables規則如下:

# Forwarding from/to outside
iptables -A FORWARD -i ${INT} -o ${EXT_0} -j ACCEPT
iptables -A FORWARD -i ${INT} -o ${EXT_1} -j ACCEPT
iptables -A FORWARD -i ${INT} -o ${EXT_2} -j ACCEPT
iptables -A FORWARD -i ${EXT_0} -o ${INT} -j ACCEPT
iptables -A FORWARD -i ${EXT_1} -o ${INT} -j ACCEPT
iptables -A FORWARD -i ${EXT_2} -o ${INT} -j ACCEPT
# NAT/Masquerade (network address translation)
iptables -t nat -A POSTROUTING -o ${EXT_0} -j MASQUERADE
iptables -t nat -A POSTROUTING -o ${EXT_1} -j MASQUERADE
iptables -t nat -A POSTROUTING -o ${EXT_2} -j MASQUERADE

假設有3個設備連接到一個內部設備的網絡共享流量,例如:

INT=tap0
EXT_0=eth0
EXT_1=wlan0
EXT_2=tun0

前面顯示了一個轉發,允許與tap設備共享有線和無線連接。

所示的轉發規則是無狀態的,用於純轉發。可以考慮限制特定的流量,設置防火牆來保護來賓和其他人。然而,這些會降低網絡性能,而簡單的網橋不包括這些。

好處:不管連接是有線還是無線,如果使用tun設備通過VPN連接到遠程站點,假設為該連接打開的tun設備是tun0,並且應用了先前的iptables規則,那麼遠程連接也將與客户機共享。這避免了客户也需要打開VPN連接。同樣,由於來賓網絡需要是靜態的,因此如果以這種方式遠程連接主機,很可能需要編輯來賓網絡上的DNS伺服器。

通過 VDE2 配置網絡[編輯 | 編輯原始碼]

本文或本章節的語言、語法或風格需要改進。參考:Help:Style

原因:This section needs serious cleanup and may contain out-of-date information.(在Talk:QEMU討論)

何為VDE?[編輯 | 編輯原始碼]

VDE 全稱為 Virtual Distributed Ethernet,作為 uml_switch 的一個擴展,是一個用於管理虛擬網絡的工具包

其基本的思想是創建一個虛擬的開關,就如插座那樣,允許虛擬機和物理機通過"插入"連接彼此。下面的配置非常簡單,然而,VDE的功能遠比展示的更強大,其能夠接入虛擬開關,在不同的主機上運行它們並監聽開關上的通信。懇請您閱讀該項目的文檔獲取更多信息。

本方法的優點在於無需sudo特權,普通用户一般沒有運行modprobe的權限。

基礎操作[編輯 | 編輯原始碼]

可以通過安裝 vde2 包來獲得 VDE 支持。

在此處配置中,我們使用tun/tap在主機上創建一塊虛擬網卡,用如下命令加載tun模塊(參閱Kernel modules獲取更多信息)

# modprobe tun

現在來創建一個虛擬開關:

# vde_switch -tap tap0 -daemon -mod 660 -group users

這條命令完成了開關創建,tap0創建並將其"插入",然後允許 users 組內的用户使用之。

該網卡已插入,然而還沒有進行配置。需要用下面的命令進行配置:

# ip addr add 192.168.100.254/24 dev tap0

現在,只需要以普通用户的身份,指定-net參數啟動KVM即可:

$ qemu-system-x86_64 -net nic -net vde -hda [...]

接下來只需同配置物理機網絡一般,對客户機網絡進行配置就行。

提示:你可能想在tap設備上設置NAT,實現在虛擬機內訪問互聯網,那就參考Internet sharing#Enable NAT獲取更多的幫助吧

啟動腳本[編輯 | 編輯原始碼]

啟動VDE的一個示例腳本:

/etc/systemd/scripts/qemu-network-env
#!/bin/sh
# QEMU/VDE network environment preparation script

# The IP configuration for the tap device that will be used for
# the virtual machine network:

TAP_DEV=tap0
TAP_IP=192.168.100.254
TAP_MASK=24
TAP_NETWORK=192.168.100.0

# Host interface
NIC=eth0

case "$1" in
  start)
        echo -n "Starting VDE network for QEMU: "

        # If you want tun kernel module to be loaded by script uncomment here
	#modprobe tun 2>/dev/null
	## Wait for the module to be loaded
 	#while ! lsmod | grep -q "^tun"; do echo "Waiting for tun device"; sleep 1; done

        # Start tap switch
        vde_switch -tap "$TAP_DEV" -daemon -mod 660 -group users

        # Bring tap interface up
        ip address add "$TAP_IP"/"$TAP_MASK" dev "$TAP_DEV"
        ip link set "$TAP_DEV" up

        # Start IP Forwarding
        echo "1" > /proc/sys/net/ipv4/ip_forward
        iptables -t nat -A POSTROUTING -s "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE
        ;;
  stop)
        echo -n "Stopping VDE network for QEMU: "
        # Delete the NAT rules
        iptables -t nat -D POSTROUTING -s "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE

        # Bring tap interface down
        ip link set "$TAP_DEV" down

        # Kill VDE switch
        pgrep vde_switch | xargs kill -TERM
        ;;
  restart|reload)
        $0 stop
        sleep 1
        $0 start
        ;;
  *)
        echo "Usage: $0 {start|stop|restart|reload}"
        exit 1
esac
exit 0

使用上面的腳本作為 systemd 服務:

/etc/systemd/system/qemu-network-env.service
[Unit]
Description=Manage VDE Switch

[Service]
Type=oneshot
ExecStart=/etc/systemd/scripts/qemu-network-env start
ExecStop=/etc/systemd/scripts/qemu-network-env stop
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

修改 qemu-network-env 權限至可執行

現在可以像其他服務一樣,啟動 qemu-network-env.service 服務。

備用方法[編輯 | 編輯原始碼]

如果上面的方法不起作用,或者説不想折騰內核配置、TUN、dnsmasq 和 iptables,可以採用下面的方法,也可以獲得同樣的效果,

# vde_switch -daemon -mod 660 -group users
# slirpvde --dhcp --daemon

然後,啟動 VM 並連接至主機網絡中:

$ qemu-system-x86_64 -net nic,macaddr=52:54:00:00:EE:03 -net vde disk_image

VDE2 網橋[編輯 | 編輯原始碼]

根據 quickhowto: qemu networking using vde, tun/tap, and bridge 所描述的. 任何連接到 vde 上的虛擬機都會暴露給外部。舉個例子,每台虛擬機都能直接從 ADSL 路由器那收到 DHCP 的配置信息。

基礎操作[編輯 | 編輯原始碼]

首先,你需要有 tun 模塊並安裝了 bridge-utils 包。

創建一個 vde2/tap 設備:

# vde_switch -tap tap0 -daemon -mod 660 -group users
# ip link set tap0 up

創建一個網橋:

# brctl addbr br0

添加設備:

# brctl addif br0 eth0
# brctl addif br0 tap0

配置網橋接口:

# dhcpcd br0

啟動腳本[編輯 | 編輯原始碼]

所有設備應該都設置好了,且只有網橋擁有IP位址。對於網橋上的物理設備(比如eth0),可以通過netctl使用一個自定義的配置文件完成上面所述設置:

/etc/netctl/ethernet-noip
Description='A more versatile static Ethernet connection'
Interface=eth0
Connection=ethernet
IP=no

下面的systemd服務用於為users用户組內的成員創建和啟動VDE2 tap網卡。

/etc/systemd/system/vde2@.service
[Unit]
Description=Network Connectivity for %i
Wants=network.target
Before=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/vde_switch -tap %i -daemon -mod 660 -group users
ExecStart=/usr/bin/ip link set dev %i up
ExecStop=/usr/bin/ip addr flush dev %i
ExecStop=/usr/bin/ip link set dev %i down

[Install]
WantedBy=multi-user.target

最後,通過 netctl 創建網橋

簡化配置參數[編輯 | 編輯原始碼]

如果你經常需要以不同的網絡配置選項運行QEMU,就會發現時常得輸入大量的 -netdev-device 選項組合,這些需要大量重複性的勞動。可以用 -nic 選項將二者結合,就如下面這樣:

-netdev tap,id=network0,ifname=tap0,script=no,downscript=no,vhost=on -device virtio-net-pci,netdev=network0

可簡化為:

-nic tap,script=no,downscript=no,vhost=on,model=virtio-net-pci

要注意的是缺失了網絡ID,因此將會以model=創建這些設備。{ic|-nic}}命令的前半部分參數正是-netdev的參數,而後半部分參數(model=之後的部分)則與設備有關,原本設備所提供的參數同樣可以在此使用(例如,可以指定smb=)。若要完全禁用網絡,可以用-nic none

參閱 QEMU networking文檔了解更多的相關參數。

圖形[編輯 | 編輯原始碼]

QEMU can emulate a standard graphic card text mode using -display curses command line option. This allows to type text and see text output directly inside a text terminal. Alternatively, -nographic serves a similar purpose.

QEMU 可以根據 -vga type 參數模擬多種不同的顯卡,可用的選項為 std,qxl,vmware,virtio,cirrusnone

std[編輯 | 編輯原始碼]

使用 -vga std 你可以得到最高 2560 x 1600 像素的解像度。從 QEMU 2.2 開始是默認選項。

qxl[編輯 | 編輯原始碼]

QXL是一個支持 2D 的並行虛擬化圖形驅動。需要在客户機中安裝驅動並在啟動 QEMU 時設置 -vga qxl 選項。你可能也會想使用 #SPICE 優化 QXL 的圖形表現。

在Linux客户機中,需要加載 qxlbochs_drm 這兩個內核模塊,以獲得一個比較好的效果。

QXL 設備的默認 VGA 內存大小為 16M,這樣的內存大小最高支持 QHD (2560x1440) 的解像度,如果想要一個更高的解像度,請增加vga_memmb

vmware[編輯 | 編輯原始碼]

儘管Bug有點多,但相比於std和cirrus它的表現會更好。對於Arch Linux客户機來説可以安裝 xf86-video-vmwarexf86-input-vmmouse 獲取VMware驅動。

virtio[編輯 | 編輯原始碼]

virtio-vga / virtio-gpu 是一個基於virgl的3D並行虛擬化圖形驅動。目前依舊處於開發中,僅支持最近的(>= 4.4)的Linux客户機,且需要以gallium-drivers=virgl選項編譯mesa (>=11.2)。

若要在客户機上啟用3D加速,那麼需要用 -device virtio-vga-gl 選項選擇此vga,並用 -display sdl,gl=on-display gtk,gl=on 在顯示設備上啟用 opengl 上下文,這兩個選項分別適用於 sdl 輸出和 gtk 輸出。如果配置成功了,那麼在客户機的 kernel log 裡可以看到:

# dmesg | grep drm 
[drm] pci: virtio-vga detected
[drm] virgl 3d acceleration enabled

cirrus[編輯 | 編輯原始碼]

cirrus 是2.2之前默認的圖形選項,不應當在現代作業系統中使用它。

none[編輯 | 編輯原始碼]

這就像一台完全沒有 VGA 卡的 PC,無法通過 -vnc 訪問它。另外,這種情況與使用 -nographic 選項不同,-nographic 會讓 QEMU 模擬 VGA 卡,只是關閉了 SDL 輸出。

SPICE[編輯 | 編輯原始碼]

SPICE project 旨在為用户提供一種完全開源的方式,無縫地對虛擬機進行遠程訪問。

在宿主機上啟用 SPICE 支持[編輯 | 編輯原始碼]

下面是一個啟用SPICE作為遠程桌面協議的例子,並支持複製和粘貼操作:

$ qemu-system-x86_64 -vga qxl -device virtio-serial-pci -spice port=5930,disable-ticketing=on -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent

這些參數的含義如下:

  1. -device virtio-serial-pci 添加一塊 virtio-serial 設備
  2. -spice port=5930,disable-ticketing 在 TCP 5930 端口上進行 spice 頻道的監聽,允許客户端不經驗證即可連接。
提示:使用 Unix 套接字 而非 TCP 端口不會涉及宿主機系統的網絡棧,也不意味着可以對數據包進行封裝和解封以使用網絡和其它相關的協議。這些套接字僅通過硬盤上的 inode 進行表示,這麼做是出於性能上的考慮。Unix 套接字可以使用 -spice unix=on,addr=/tmp/vm_spice.socket,disable-ticketing=on 代替上述參數。
  1. -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 在 virtio-serial 設備上為 spice vdagent 打開一個端口。
  2. -chardev spicevmc,id=spicechannel0,name=vdagent 為該端口添加一塊 spicevmc 字符設備。virtserialportchardev= 選項需要與 chardevid= 相符,在本例中是 spicechannel0。將端口名字設置為 com.redhat.spice.0 也很重要,因為它就是 vdagent 在客户機上所搜索的命名空間。最後,指定 name=vdagent 選項使得 spice 知道該頻道的服務對象。

通過 SPICE 客户端連接到客户機[編輯 | 編輯原始碼]

若要連接到客户機上必須要有一個 SPICE 客户端。在 Arch 中,有如下可用的客户端:

  • virt-viewer — 協議開發者所推薦的 SPICE 客户端,是 virt-manager 項目的子集。
https://virt-manager.org/ || virt-viewer
  • spice-gtk — SPICE GTK 客户端,SPICE 項目的一個子集,作為小部件嵌入其它應用中。
https://www.spice-space.org/ || spice-gtk

若需要能在智能手機上運行的客户端,或者其他平台的客户端,參照 spice-space download 中的 Other clients 章節。

手動開啟 SPICE 客户端[編輯 | 編輯原始碼]

連接到一個監聽在 Unix 套接字 /tmp/vm_spice.socket 上的客户機的方法是用 $ remote-viewer spice+unix:///tmp/vm_spice.socket$ spicy --uri="spice+unix:///tmp/vm_spice.socket" 命令手動運行 SPICE 客户端,使用的客户端取決於你的喜好。SPICE 模式下的 QEMU 就如一個遠程桌面伺服器,可能使用 -daemonize 參數以daemon 模式運行 QEMU 會更方便一些。

提示:可以用下面的命令,通過 SSH 隧道連接到客户機:
$ ssh -fL 5999:localhost:5930 my.domain.org sleep 10; spicy -h 127.0.0.1 -p 5999
。這個例子中 spicy 連接到了本地的 5999 端口,該端口通過 SSH 轉發至 my.domain.org 上的 SPICE 伺服器端口 5930。要注意 -f 選項讓 ssh 在後台執行了 sleep 10 命令。這種情況下,在客户端存活時 ssh 會話保持運行,在客户端結束運行時將自動關閉 ssh 會話。

QEMU 運行時啟動SPICE[編輯 | 編輯原始碼]

QEMU 可以自動地開啟一個 SPICE 客户端並創建一個合適的套接字。如果通過 -display spice-app 參數將顯示設置為SPICE,那麼將會使用系統默認的 SPICE 客户端作為 viewer,默認的客户端取決於你的mimeapps.list文件。

在客户機上開啟SPICE的支持[編輯 | 編輯原始碼]

對於Arch Linux客户機,如要支持多屏和共享剪貼板,需要安裝以下的包:

  • spice-vdagent: Spice的xorg客户端代理,使得用户能夠在客户端和X-session之間進行複製和粘貼等。(Refer to this issue, until fixed, for workarounds to get this to work on non-GNOME desktops.)
  • xf86-video-qxl: Xorg X11 qxl視頻驅動

對於其它的作業系統客户機, 參照spice-space downloadGuest章節。

開啟 SPICE 口令驗證[編輯 | 編輯原始碼]

若要啟用 SPICE 的口令驗證,需要從 -spice 的參數中移除 disable-ticketing,改為 password=yourpassword,例如:

$ qemu-system-x86_64 -vga qxl -spice port=5900,password=yourpassword -device virtio-serial-pci -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent

現在 SPICE 客户端在連接 SPICE 伺服器的時候應該就會進行口令詢問了。

用 TLS 對與 SPICE 的通信進行加密[編輯 | 編輯原始碼]

同樣可以為客户端與 SPICE 伺服器的通信配置 TLS 加密。首先,需要有一個包含如下文件的目錄(文件名必須與下面保持一致):

  • ca-cert.pem: CA 主證書。
  • server-cert.pem: ca-cert.pem 簽名後的伺服器證書。
  • server-key.pem: 伺服器的私鑰。

Spice User Manual還展示了使用伺服器自己生成的CA生成自簽名證書的例子。

這些完成後,你可以用前文描述的 -spice 的參數在 QEMU 啟動時自動開啟 SPICE:-spice tls-port=5901,password=yourpassword,x509-dir=/path/to/pki_certs,其中 /path/to/pki_certs 代表包含那三個文件的目錄。

現在可以用 virt-viewer 連接到伺服器了:

$ remote-viewer spice://hostname?tls-port=5901 --spice-ca-file=/path/to/ca-cert.pem --spice-host-subject="C=XX,L=city,O=organization,CN=hostname" --spice-secure-channels=all

要記住的是,--spice-host-subject 參數需要根據你的 server-cert.pem 中的子條目進行設置。此外還需要將 ca-cert.pem 複製到每個客户端上用於驗證伺服器證書。

提示:使用下面的命令,就可以獲得伺服器證書中的子條目格式,可用於 --spice-host-subject 參數中(以逗號進行分隔):
$ openssl x509 -noout -subject -in server-cert.pem | cut -d' ' -f2- | sed 's/\///' | sed 's/\//,/g'

等效的 spice-gtk 命令為:

$ spicy -h hostname -s 5901 --spice-ca-file=ca-cert.pem --spice-host-subject="C=XX,L=city,O=organization,CN=hostname" --spice-secure-channels=all

VNC[編輯 | 編輯原始碼]

可以用-vnc :X選項將QEMU的VGA輸出重定向至VNC會話中。將X替換為輸出目標的編號(0代表之後監聽在5900,1代表監聽在5901...)。

$ qemu-system-x86_64 -vnc :0

#開機時啟動QEMU虛擬機這一小節中同樣提供了一個VNC的示例。

警吿: 默認的 VNC 伺服器沒有使用任何驗證手段,用户可以從任何主機上連接到 VNC。

基本的口令驗證[編輯 | 編輯原始碼]

可以通過使用password選項很容易地設置訪問口令。必須在QEMU Monitor中指定口令,僅當用户提供口令時才有可能連接到VNC。

$ qemu-system-x86_64 -vnc :0,password -monitor stdio

在QEMU Monitor中設置口令需使用 change vnc password 命令,然後指定一個口令。

底下的命令將在啟動 VNC 時直接為其設置口令:

$ printf "change vnc password\n%s\n" MYPASSWORD | qemu-system-x86_64 -vnc :0,password -monitor stdio
注意: 口令被限制在8個字符內,可以用暴力破解的方式猜到口令。因此在公網上推薦使用更細緻的保護措施。

音頻[編輯 | 編輯原始碼]

創建音頻後端[編輯 | 編輯原始碼]

-audiodev 標識用於設定後端音頻驅動及其相關選項。

To list availabe audio backend drivers:

$ qemu-system-x86_64 -audiodev help

qemu(1)man 頁面中詳細列出了可用的後端音頻驅動以及可選的設置項。

最簡單的情況下,你需要選擇一個驅動並設置一個 id。以 PulseAudio 為例:

-audiodev pa,id=snd0

使用音頻後端[編輯 | 編輯原始碼]

Intel HD Audio[編輯 | 編輯原始碼]

模擬 Intel HD Audio 需要添加控制器和編解碼器設備。可以用如下命令列出可用的 Intel HDA Audio 設備:

$ qemu-system-x86_64 -device help | grep hda

添加音頻控制器:

-device ich9-intel-hda

添加音頻編解碼器並將其映射到宿主機的音頻後端 id 上。

-device hda-output,audiodev=snd0

Intel 82801AA AC97[編輯 | 編輯原始碼]

模擬 AC97 需要添加聲卡設備並將其映射到宿主機的一個音頻後端 id 上。

-device AC97,audiodev=snd0
注意:
  • 如果沒有提供 audiodev 後端,QEMU 會自動查找並添加它,這隻適用於單個 audiodev。例如,-device intel-hda -device hda-duplex 將使用默認的 audiodev 後端在客户機上模擬 intel-hda
  • 客户機的顯卡模擬驅動也可能導致聲音質量的問題,需要逐一測試以使其正常工作。你可以用 qemu-system-x86_64 -h | grep vga 列出可能的選項。

安裝 virtio 驅動[編輯 | 編輯原始碼]

QEMU 為用户提供並行虛擬化塊設備和網絡設備的能力,其是藉助 virtio 驅動實現的,擁有更好的性能表現以及更低的開銷。

  • virtio塊設備需要使用 -drive 指定一個 disk image 的參數,且需要帶上if=virtio參數:
$ qemu-system-x86_64 -drive file=disk_image,if=virtio
  • 網絡配置也是類似的:
$ qemu-system-x86_64 -nic user,model=virtio-net-pci
注意: 僅有當客户機有 virtio 設備對應的驅動時該方法才能起效,Linux 是有這方面支持的,而在 Arch Linux 中已經包含所需的驅動了,不過無法保證這些驅動能夠兼容其他作業系統。

Arch Linux 客户機[編輯 | 編輯原始碼]

要在Arch Linux客户機中使用virtio設備,必須在客户端加載以下模塊:{virtiovirtio_pcivirtio_blkvirtio_netvirtio_ring。對於32位系統來説,不需要特定的「virtio」模塊。

如果希望從 virtio 磁盤引導,ramdisk 必須包含必要的模塊。默認情況下,這是由 mkinitcpioautodetect 鈎子處理的。否則要在 /etc/mkinitcpio.conf 中使用 MODULES 數組包含必要的模塊並重新構建 ramdisk。

/etc/mkinitcpio.conf
MODULES=(virtio virtio_blk virtio_pci virtio_net)

Virtio 磁盤公認的前綴為 v(例如:vdavdb,等等)。因此,當從 virtio 磁盤啟動時,需要在 /etc/fstab/boot/grub/grub.cfg 中進行更改。

提示: 當在 /etc/fstab 和引導加載程序中通過 UUID 引用磁盤時,不需要執行任何操作。

關於使用KVM進行半虛擬化的更多信息,可以參考這裏

您可以安裝 qemu-guest-agent 來實現對 QMP 命令的支持,從而增強管理程序的管理能力。安裝完成後,您需要啟動qemu-guest-agent.service

Windows 客户機[編輯 | 編輯原始碼]

Virtio drivers for Windows[編輯 | 編輯原始碼]

Windows does not come with the virtio drivers. The latest and stable versions of the drivers are regularly built by Fedora, details on downloading the drivers are given on virtio-win on GitHub. In the following sections we will mostly use the stable ISO file provided here: virtio-win.iso. Alternatively, use virtio-winAUR.

塊設備驅動[編輯 | 編輯原始碼]

安裝一個新的Windows[編輯 | 編輯原始碼]

需要在系統安裝時通過 ISO 加載驅動,具體操作是在主磁盤設備和 Windows 安裝盤外掛載一個額外的 cdrom 設備,將系統鏡像與 virtio 驅動一同加載:

$ qemu-system-x86_64 ... \
-drive file=disk_image,index=0,media=disk,if=virtio \
-drive file=windows.iso,index=2,media=cdrom \
-drive file=virtio-win.iso,index=3,media=cdrom \
...

在安裝過程中,Windows Installer 會詢問你「Where do you want to install Windows?」,其會返回一個警吿表示沒有找到任何磁盤設備。接下來跟着如下示例中的步驟進行操作(基於Windows Server 2012 R2 with Update):

  • Select the option Load Drivers.
  • Uncheck the box for Hide drivers that are not compatible with this computer's hardware.
  • Click the browse button and open the CDROM for the virtio iso, usually named "virtio-win-XX".
  • Now browse to E:\viostor\[your-os]\amd64, select it, and confirm.

現在應該能看到 virtio 磁盤出現在列表中了,等待被選中、格式化並安裝。

將現有的 Windows VM 轉為使用 virtio[編輯 | 編輯原始碼]

可將現有的 Windows 客户機改為從 virtio 磁盤中啟動,前提是客户機中有 virtio 驅動,且該驅動在啟動期間就被加載。 We will therefore need to teach Windows to load the virtio driver at boot time before being able to boot a disk image in virtio mode.

先創建一個新的磁盤鏡像,用於搜索 virtio 驅動:

$ qemu-img create -f qcow2 fake.qcow2 1G

掛載 fake 磁盤(處於virtio模式下)和帶有驅動的CD-ROM,運行原本的Windows客户機(啟動盤依舊是處於IDE模式中):

$ qemu-system-x86_64 -m 4G -drive file=disk_image,if=ide -drive file=fake.qcow2,if=virtio -cdrom virtio-win.iso

Windows會自動檢測fake磁盤,並搜索適配的驅動。如果失敗了,前往Device Manager,找到SCSI驅動器(帶有感嘆號圖標,應處於打開狀態),點擊Update driver並選擇虛擬的CD-ROM。不要定位到CD-ROM內的文件夾了,只選擇CD-ROM設備就行,Windows會自動找到合適的驅動的。(已在Windows 7 SP1中完成測試)。

可以讓Windows從下一次起為以安全模式啟動,可以用Windows上的msconfig.exe工具完成該配置,在安全模式中所有的驅動都會在boot期間被加載,包括我們新裝的virtio驅動。只要Windows知道boot期間需要加載virtio,在未來的boot過程中Windows都會記住該設置的。

將客户機配置為安全模式啟動後,可以關機並重新啟動它,現在可以以 virtio 模式掛載 boot 磁盤:

$ qemu-system-x86_64 -m 4G -drive file=disk_image,if=virtio

現在應當能攜帶 virtio 驅動啟動到安全模式中,你可以返回到 msconfig.exe 中禁用安全模式並重啟 Windows。

注意: 如果使用if=virtio參數時碰上了藍屏問題,這代表virtio磁盤驅動可能沒有在boot期間被安裝,以安全模式重啟之,然後檢查你的驅動配置。

網絡驅動[編輯 | 編輯原始碼]

安裝virtio網絡驅動程序要容易一些,只需如上所述添加-net參數即可。

$ qemu-system-i386 -m 4G -vga std -drive file=windows_disk_image,if=virtio -net nic,model=virtio -cdrom virtio-win-0.1-185.iso

Windows將檢測網絡適配器並嘗試為其找到驅動程序。如果失敗,請轉到「設備管理器」,找到帶有感嘆號圖標的網絡適配器(雙擊打開),切換到驅動程序並單擊「更新驅動程序」,然後選擇虛擬CD-ROM。別忘了選中顯示要遞歸搜索目錄的複選框。

Balloon 驅動[編輯 | 編輯原始碼]

如果想要追蹤客户機內存狀態(比如通過virshdommemstat命令)或者在運行時改變客户機內存大小(儘管依然無法改變實際的內存大小,不過可以通過inflating balloon驅動限制內存的使用),那麼請在客户機上安裝balloon驅動吧。

安裝該驅動需要前往Device Manager,其位於System devices內的PCI standard RAM Controller中(未識別的PCI控制設備則在Other devices中)。選擇Update driver,在打開的窗口中選擇Browse my computer...,然後選擇CD-ROM(記得勾上Include subdirectories選項),安裝完成後重啟,驅動就安裝成功了。現在可以如氣球打氣一般調整內存限制(例如通過hmp命令balloon memory_size,該命令會使balloon從客户機中儘可能地奪取內存,將客户機的內存大小限制至memory_size)。然而,現在依然無法追蹤內存的狀態,我們還需要正確地安裝Balloon服務才行。以管理員身份啟動命令行,前往CD-ROM中的Balloon目錄,然後在目錄下找到對應系統和架構的地方。當深入至 amd64 (x86) 目錄時,運行blnsrv.exe -i進行安裝,安裝之後virsh命令dommemstat就會輸出命令所支持的各種數據。

FreeBSD客户機[編輯 | 編輯原始碼]

如果你使用的是FreeBSD 8.3之後10.0-CURRENT之間的版本, 那麼無論內核中是否包含了virtio-kmod, 都需要安裝emulators/virtio-kmod端口。安裝之後請在/boot/loader.conf添加如下內容:

virtio_load="YES"
virtio_pci_load="YES"
virtio_blk_load="YES"
if_vtnet_load="YES"
virtio_balloon_load="YES"

按照下面修改 /etc/fstab

# sed -ibak "s/ada/vtbd/g" /etc/fstab

注意確認 /etc/fstab 內容與該命令的預期效果相同,如果出錯了就通過 rescue CD 啟動,然後將 /etc/fstab.bak 複製到 /etc/fstab

QEMU 監視器[編輯 | 編輯原始碼]

QEMU運行時會提供一個監視器 console 界面以方便用户同虛擬機進行交互。QEMU 監視器提供了許多有趣的功能,例如獲取當前虛擬機的信息,熱插拔設備,創建快照等。在 QEMU 監視器 console 中運行 help? 命令,或者閱讀官方 QEMU 文檔獲得完整的命令列表。

訪問 QEMU 監視器 Console[編輯 | 編輯原始碼]

圖形化界面[編輯 | 編輯原始碼]

當使用默認的 std 圖形選項時,可以通過按下 Ctrl+Alt+2 組合鍵或從QEMU窗口上的 View > compatmonitor0 訪問到 QEMU 監視器。若要返回到虛擬機的圖形界面,那麼按下 Ctrl+Alt+1 或者 View > VGA 就行。

然而,這種標準的訪問方式不夠方便,而且並不是在QEMU的所有圖形化輸出方式中都適用。

Telnet[編輯 | 編輯原始碼]

啟動 QEMU 時帶上 -monitor telnet:127.0.0.1:port,server,nowait 參數可以啟用 telnet。虛擬機啟動後可以通過 telnet 訪問到監視器:

$ telnet 127.0.0.1 port
注意: 如果指定 127.0.0.1 作為監聽地址,那麼只能在運行 QEMU 的宿主機上連接到該監視器。如果想要遠程訪問,QEMU需要在 0.0.0.0 上進行監聽:-monitor telnet:0.0.0.0:port,server,nowait。還要記住的是,最好對防火牆進行配置,該連接是完全不進行認證和加密的,因此需要通過防火牆確保本地網絡環境是可信的。

UNIX 套接字[編輯 | 編輯原始碼]

通過 -monitor unix:socketfile,server,nowait 參數運行QEMU,之後就可以通過 socatnmapopenbsd-netcat 連接到監視器上。

例如,如果QEMU是通過如下命令啟動:

$ qemu-system-x86_64 -monitor unix:/tmp/monitor.sock,server,nowait [...]

就可以像這樣連接到監視器上:

$ socat - UNIX-CONNECT:/tmp/monitor.sock

或者通過這種方式:

$ nc -U /tmp/monitor.sock

也可以使用 nmap

$ ncat -U /tmp/monitor.sock

TCP[編輯 | 編輯原始碼]

可以使用 -monitor tcp:127.0.0.1:port,server,nowait 參數將監視器暴露於TCP端口上,然後用 netcat(openbsd-netcatgnu-netcat 都可以)進行連接:

$ nc 127.0.0.1 port
注意: 為了能夠從其它設備上通過 TCP 套接字訪問到監視器,而不僅僅從運行QEMU的主機上連接,需要像前面Telnet中描述的那樣,在0.0.0.0地址上進行監聽。

標準 I/O[編輯 | 編輯原始碼]

如果以 -monitor stdio 參數運行QEMU,那麼其實是可以在運行 QEMU 的終端下訪問到監視器的。

在 Monitor conosle 下向虛擬機發送按鍵行為[編輯 | 編輯原始碼]

由於在某些配置下,宿主機可能會攔截一些按鍵組合另作他用,這導致要在虛擬機中觸發一些特定按鍵組合變得有些困難(一個顯然的例子就是Ctrl+Alt+F*組合,該組合用於改變當前的tty)。我們採用在monitor console下發送按鍵組合的方式解決該問題。只需切換到monitor console下,然後使用sendkey命令,即可將按鍵轉發至虛擬機中,例如:

(qemu) sendkey ctrl-alt-f2

通過 monitor console 創建快照和管理快照[編輯 | 編輯原始碼]

注意: 該特性支持 qcow2 格式的虛擬機磁盤鏡像,對於 raw 是無效的。

有時候我們很需要將虛擬機的當前狀態進行保存,或是將虛擬機重置到之前的快照狀態,而且最好是隨時能進行這些操作。QEMU monitor console為用户提供了必要的功能,進行快照創建,快照管理,以及快照恢復。

  • Use savevm name 用於創建一個名為name的快照。
  • Use loadvm name 用於將虛擬機狀態恢復至快照name
  • Use delvm name 用於刪除快照name
  • Use info snapshots 用於查看保存的快照列表,這些快照由一個自增長的ID和標籤名(用户創建快照時賦予)進行標識。

以凍結模式運行虛擬機[編輯 | 編輯原始碼]

QEMU支持以凍結態運行虛擬機(需使用-snapshot參數),換句話説,虛擬機關閉時,對於虛擬機的一切修改都會丟棄。當用户對磁盤鏡像寫入時,這些變動最終寫入的位置是/tmp目錄下的一個臨時文件,QEMU關機時將會把他們丟棄。

不過,即使虛擬機運行於凍結狀態下,依舊可以通過monitor console將這些變化寫入磁盤鏡像(如果你想的話)。使用下面的命令:

(qemu) commit all

另外如果在凍結狀態下創建快照,這些快照在QEMU退出時都會被丟棄,除非你顯式地commit了他們。

monitor console 中的開機和暫停命令[編輯 | 編輯原始碼]

在QEMU monitor console下也可以模擬對物理機的一些操作:

  • system_powerdown 會向虛擬機發送ACPI關機信號,效果就類似物理機上按下電源按鈕。
  • system_reset 會重置虛擬機,類似物理機上的重置按鈕。該操作可能導致數據丟失或文件系統的損壞,這是因為虛擬機並不是"乾淨地"重啟的。
  • stop 會暫停虛擬機。
  • cont 使暫停的虛擬機恢復運行。

虛擬機截屏[編輯 | 編輯原始碼]

可以在monitor console下運行該命令,獲取PPM格式的截屏圖片:

(qemu) screendump file.ppm

QEMU 機器協議[編輯 | 編輯原始碼]

QEMU機器協議(QMP)是一個基於JSON格式的協議,使得其他應用程式可以通過該協議控制QEMU實例。類似#QEMU 監視器,其提供了與運行中的虛擬機進行交互的能力,且能夠編程進行控制。關於QMP各命令的描述可以在這個qmp-commands連結中找到。

啟動 QMP[編輯 | 編輯原始碼]

使用QMP協議來控制虛擬機的通常做法是在啟動QEMU時使用-qmp打開一個 TCP 套接字。底下是一個使用 TCP 4444 端口的例子:

$ qemu-system-x86_64 [...] -qmp tcp:localhost:4444,server,nowait

而與QMP代理進行通信的一個選擇是使用 netcat:

nc localhost 4444
{"QMP": {"version": {"qemu": {"micro": 0, "minor": 1, "major": 3}, "package": ""}, "capabilities": []} } 

在目前這個階段,其能識別的命令僅有qmp_capabilities,QMP將進入了命令模式。敲下:

{"execute": "qmp_capabilities"}

現在,QMP可以接收命令了。要查看QMP接受的命令列表,使用:

{"execute": "query-commands"}

即時將子鏡像合併至父鏡像中[編輯 | 編輯原始碼]

通過發起一個block-commit可以將一個正處於運行態的快照合併到其父結點上。下面的例子是其最簡單的一種形式,將把子鏡像提交至父鏡像中:

{"execute": "block-commit", "arguments": {"device": "devicename"}}

QMP收到該命令後,處理程序將會尋找基鏡像,把該鏡像由只讀轉為可讀寫模式,然後完成commit的任務。

一旦block-commit操作完成,將會觸發一個BLOCK_JOB_READY事件,發出同步完成的信號。當然也可以用一種更優雅的方式完成該操作,改為使用block-job-complete

{"execute": "block-job-complete", "arguments": {"device": "devicename"}}

在發出該命令之前,commit操作將會保持活動狀態。 任務完成後,基鏡像將會保持在可讀寫模式,並變為active層。另一方面,子鏡像將變得不可使用,用户有責任將其清除。

提示:執行query-block命令並對輸出進行解析可以獲取設備列表和其對應名字。設備名在 device 字段中,例如本例中磁盤設備名就是 ide0-hd0
{"execute": "query-block"}
{"return": [{"io-status": "ok", "device": "ide0-hd0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"backing-image": {"virtual-size": 27074281472, "filename": "parent.qcow2", ... } 

即時創建一個新的快照[編輯 | 編輯原始碼]

為運行中的鏡像創建一個快照:

{"execute": "blockdev-snapshot-sync", "arguments": {"device": "devicename","snapshot-file": "new_snapshot_name.qcow2"}}

該命令將會創建一個名為 new_snapshot_name.qcow2 的堆疊文件,該快照也將成為新的活動層。

技巧[編輯 | 編輯原始碼]

改善虛擬機的性能表現[編輯 | 編輯原始碼]

底下是一些可以改善虛擬機性能表現的技術,例如:

  • 啟用#啟用 KVM:QEMU的啟動命令加上 -enable-kvm 選項。
  • 通過 -cpu host 選項讓 QEMU 模擬宿主機上的特定 CPU,如果沒有該選項 QEMU 嘗試模擬的是一個更為通用的 CPU。
  • 特別的,如果客户機是 Windows,啟用Hyper-V enlightenments可以改善性能:-cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time.
  • multiple cores can be assigned to the guest using the -smp cores=x,threads=y,sockets=1,maxcpus=z option. The threads parameter is used to assign SMT cores. Leaving a physical core for QEMU, the hypervisor and the host system to operate unimpeded is highly beneficial.
  • 檢查是否為虛擬機分配的足夠的內存。默認情況下,QEMU僅僅為每台虛擬機分配 128MiB 的內存,可以使用 -m 選項分配更多的內存。例如,-m 1024 代表啟動一台內存為 1024MiB 的虛擬機,-m 4G則為4GiB的內存。
  • 如果客户機作業系統支持相關的驅動,可以使用virtio創建網絡設備或塊設備,詳情可參考 #Installing virtio drivers
  • 使用 TAP 設備代替 user-mode 網絡,參閱#Tap 網絡
  • 如果客户機需要進行大量的磁盤寫工作,在宿主機文件系統上設置合適的掛載選項可以優化該工作。例如,可以用barrier=0選項掛載一個 Ext4 文件系統。在使用這些性能強化選項之前最好閱讀相關文檔,因為性能上的提升通常伴隨着數據完整性下降的代價。
  • 如果有一塊原始磁盤或分區,你可能會想要禁用緩存:
    $ qemu-system-x86_64 -drive file=/dev/disk,if=virtio,cache=none
  • 使用原生的Linux AIO:
    $ qemu-system-x86_64 -drive file=disk_image,if=virtio,aio=native,cache.direct=on
  • 如果正同時運行多台虛擬機,而它們擁有同樣的作業系統,可以通過啟用內核頁歸併節省內存。參閱#開啟 KSM
  • 在一些情況下,可以在運行時從安裝了 balloon 驅動的客户機上回收內存,這需要 QEMU 啟動該客户機時使用-device virtio-balloon選項。
  • 儘管不是很穩定,可以使用 ICH-9 AHCI 控制器的仿真層。AHCI 的仿真模擬支持 NCQ,因此可以同時處理多個讀寫請求:
    $ qemu-system-x86_64 -drive id=disk,file=disk_image,if=none -device ich9-ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0

參閱 https://www.linux-kvm.org/page/Tuning_KVM 獲取更多信息。

開機時啟動QEMU虛擬機[編輯 | 編輯原始碼]

通過 libvirt 實現[編輯 | 編輯原始碼]

如果虛擬機是通過 libvirt 設置的,可以用 virsh autostart 將其配置為開機自啟,或者通過 virt-manager GUI 中虛擬機的 Boot Options,選擇 "Start virtual machine on host boot up" 實現開機自啟。

通過 systemd 服務實現[編輯 | 編輯原始碼]

可以用如下的 systemd unit 和 config 配置開機時啟動 QEMU VM。

/etc/systemd/system/qemu@.service
[Unit]
Description=QEMU virtual machine

[Service]
Environment="haltcmd=kill -INT $MAINPID"
EnvironmentFile=/etc/conf.d/qemu.d/%i
ExecStart=/usr/bin/qemu-system-x86_64 -name %i -enable-kvm -m 512 -nographic $args
ExecStop=/usr/bin/bash -c ${haltcmd}
ExecStop=/usr/bin/bash -c 'while nc localhost 7100; do sleep 1; done'

[Install]
WantedBy=multi-user.target
注意: 為了方便地結束任務,該 service 會等待至 console 端口被釋放(這意味着 VM 已被關閉)。

接着按單個 VM 創建配置文件,命名為 /etc/conf.d/qemu.d/VM 名稱,在其中設置好 argshaltcmd 變量,配置示例:

/etc/conf.d/qemu.d/one
args="-hda /dev/vg0/vm1 -serial telnet:localhost:7000,server,nowait,nodelay \
 -monitor telnet:localhost:7100,server,nowait,nodelay -vnc :0"

haltcmd="echo 'system_powerdown' | nc localhost 7100" # or netcat/ncat
/etc/conf.d/qemu.d/two
args="-hda /srv/kvm/vm2 -serial telnet:localhost:7001,server,nowait,nodelay -vnc :1"

haltcmd="ssh powermanager@vm2 sudo poweroff"

對該變量的描述如下:

  • args - 使用的 QEMU 命令行參數。
  • haltcmd - 安全關閉虛擬機的命令,在第一個例子中,QEMU monitor 是通過 -monitor telnet:.. 選項暴露至 telnet,因而關閉虛擬機是通過 nc 命令在 monitor console 中發送 system_powerdown,完成 ACPI 關機的工作。在另一個例子裏,使用的則是 SSH。

若要設置啟動時運行哪個虛擬機,啟用 qemu@vm_name.service 這個 systemd 單元。

鼠標整合[編輯 | 編輯原始碼]

添加 -usb -device usb-tablet 選項以避免點擊客户機系統的窗口時鼠標被捕獲。該選項代表 QEMU 能夠在不捕獲鼠標的情況下,向系統報吿鼠標的位置,該選項啟用時還會覆蓋 PS/2 鼠標模擬功能。例如:

$ qemu-system-x86_64 -hda disk_image -m 512 -usb -device usb-tablet

如果該命令不起作用,試試 -vga qxl 參數,並看看#鼠標指針抖動或者不穩定的操作指導。

宿主機的USB設備傳遞至虛擬機[編輯 | 編輯原始碼]

從客户機訪問連接到宿主機USB口的設備是可能的,首先需要識別設備連接的位置,可以用lsusb命令找到設備連接位置,例如:

$ lsusb
...
Bus 003 Device 007: ID 0781:5406 SanDisk Corp. Cruzer Micro U3

上面以粗體顯示的數字分別用於標識「 host_bus」和「 host_addr」或者「 vendor_id」和「 product_id」。

基本的思想是在 QEMU 中 -device usb-ehci,id=ehci-device qemu-xhci,id=xhci 分別對 EHCI (USB 2) 或 XHCI (USB 1.1,USB 2,USB 3) 控制器進行模擬,然後將物理設備通過 -device usb-host,.. 選項進行添加。在本節中的剩餘部分,controller_id要麼是 ehci,要麼是 xhci

接着,這裏有兩種方法通過qemu連接到宿主機的USB:

  1. 識別出該設備,並將其連接至任一總線以及宿主機上的地址,通用的語法如下:
    -device usb-host,bus=controller_id.0,vendorid=0xvendor_id,productid=0xproduct_id
    。Applied to the device used in the example above, it becomes:
    -device usb-ehci,id=ehci -device usb-host,bus=ehci.0,vendorid=0x0781,productid=0x5406
    ;此外也可以在上面的選項中添加...,port=port_number 設置,用於指定設備添加至虛擬機控制器上的哪個物理端口。該設置在為 VM 添加多個設備時比很有用。另一個方案是使用 QEMU 5.1.0 之後出現的 usb-hosthostdevice屬性,語法為:
    -device qemu-xhci,id=xhci -device usb-host,hostdevice=/dev/bus/usb/003/007
  2. 若要添加一個已連接至特定USB總線和地址的設備,語法為:
    -device usb-host,bus=controller_id.0,hostbus=host_bus,host_addr=host_addr
    ,將其中的參數修改至該總線和地址即可,拿上面的例子來説,需修改為:
    -device usb-ehci,id=ehci -device usb-host,bus=ehci.0,hostbus=3,hostaddr=7
注意: 如果運行 QEMU 時遇到了權限方面的錯誤,可以閱讀 udev#About udev rules 獲取更多信息,以了解如何為設備設定合適的權限。

使用 SPICE 進行 USB 重定向[編輯 | 編輯原始碼]

使用#SPICE時可以將USB設備從客户端重定向至虛擬機中,無需使用QEMU命令。還支持為配置USB重定向插槽數(插槽數將決定可同時重定向的最大設備數)。相比於前面那種使用-usbdevice進行重定向的方法,SPICE方法的優勢在於可以在虛擬機啟動後USB設備熱插拔,移除或添加USB設備時無需停機。這個方法還允許通過網絡將客户端的USB設備重定向至服務端。總之,其是在QEMU虛擬機中使用USB設備最靈活的方法。

我們需要為每個所需的USB重定向插槽添加一個EHCI/UHCI控制器,以及每個插槽添加一個SPICE重定向通道。例如,將下面的選項加入到所使用的QEMU命令中,以SPICE模式啟動虛擬機時將會添加三個用於重定向的USB插槽:

-device ich9-usb-ehci1,id=usb \
-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,multifunction=on \
-device ich9-usb-uhci2,masterbus=usb.0,firstport=2 \
-device ich9-usb-uhci3,masterbus=usb.0,firstport=4 \
-chardev spicevmc,name=usbredir,id=usbredirchardev1 -device usb-redir,chardev=usbredirchardev1,id=usbredirdev1 \
-chardev spicevmc,name=usbredir,id=usbredirchardev2 -device usb-redir,chardev=usbredirchardev2,id=usbredirdev2 \
-chardev spicevmc,name=usbredir,id=usbredirchardev3 -device usb-redir,chardev=usbredirchardev3,id=usbredirdev3

參閱 SPICE/usbredir 獲取更多信息。

spice-gtk中的spicy(Input > Select USB Devices for redirection)和virt-viewer中的remote-viewer(File > USB device selection)都支持該特性。請確保你已在客户機上安裝必要的SPICE Guest Tools,以使得該功能正常運作(參見#SPICE節獲得更多信息)。

警吿: 需要牢記一點,當將USB設備從客户端重定向至服務端時,在客户端所在的作業系統上都無法使用該USB了,除非停止重定向。尤其重要的是千萬不要將輸入設備重定向(即不要將鼠標和鍵盤重定向),這麼做會使得你難以訪問到SPICE客户端的菜單而無法撤銷該操作,因為在輸入設備被重定向至虛擬機後,客户端無法響應它們的操作。

Automatic USB forwarding with udev[編輯 | 編輯原始碼]

Normally, forwarded devices must be available at the boot time of the virtual machine to be forwarded. If that device is disconnected, it will not be forwarded anymore.

You can use udev rules to automatically attach a device when it comes online. Create a hostdev entry somewhere on disk. chown it to root to prevent other users modifying it.

/usr/local/hostdev-mydevice.xml
<hostdev mode='subsystem' type='usb'>
  
    <vendor id='0x03f0'/>
    <product id='0x4217'/>
</hostdev>

Then create a udev rule which will attach/detach the device:

/usr/lib/udev/rules.d/90-libvirt-mydevice
ACTION=="add", \
    SUBSYSTEM=="usb", \
    ENV{ID_VENDOR_ID}=="03f0", \
    ENV{ID_MODEL_ID}=="4217", \
    RUN+="/usr/bin/virsh attach-device GUESTNAME /usr/local/hostdev-mydevice.xml"
ACTION=="remove", \
    SUBSYSTEM=="usb", \
    ENV{ID_VENDOR_ID}=="03f0", \
    ENV{ID_MODEL_ID}=="4217", \
    RUN+="/usr/bin/virsh detach-device GUESTNAME /usr/local/hostdev-mydevice.xml"

Source and further reading.

開啟KSM[編輯 | 編輯原始碼]

Kernel Samepage Merging (KSM) 是Linux內核的一個特性,允許應用程式向內核申請同其他申請頁歸併的進程進行頁歸併,KSM機制允許客户虛擬機之間進行頁共享。當許多客户機運行相似的作業系統時,這個機制可以節省客觀的內存。

注意: 儘管KSM可能減小內存佔用量,其增加了CPU負擔。此外要注意的是使用該機制可能產生一些安全問題,參見Wikipedia:Kernel same-page merging

啟用KSM:

# echo 1 > /sys/kernel/mm/ksm/run

使之常駐,使用 systemd 的臨時文件

/etc/tmpfiles.d/ksm.conf
w /sys/kernel/mm/ksm/run - - - - 1

當 KSM 啟用,而正好有準備進行歸併的頁,(比如,至少有兩個相似的 VM 正在運行),那麼 /sys/kernel/mm/ksm/pages_shared 應會是非零的。參閱 https://www.kernel.org/doc/html/latest/admin-guide/mm/ksm.html 了解更多信息。

提示:查看KSM性能的一種簡單方法是列出此目錄下的所有文件內容:
$ grep -r . /sys/kernel/mm/ksm/

多屏支持[編輯 | 編輯原始碼]

Linux的QXL驅動支持默認支持四頭(虛擬屏幕),可以通過qxl.heads=N這一內核參數進行變更。

QXL設備的默認VGA內存大小為16M(VRAM大小為64M),在想使用兩塊1920x1200顯示器時(需要2 × 1920 × 4 (色深) × 1200 = 17.6 MiB VGA內存)是不夠用的。用-vga none -device qxl-vga,vgamem_mb=32選項代替-vga qxl可以對該屬性進行變更。如果你將vgamem_mb增大至64M以上,則還需要增大vram_size_mb選項的值。

Custom display resolution[編輯 | 編輯原始碼]

A custom display resolution can be set with -device VGA,edid=on,xres=1280,yres=720 (see EDID and display resolution).

複製和粘貼[編輯 | 編輯原始碼]

在宿主機和客户機之間共享剪貼板的方法之一是使用SPICE遠程桌面協議,通過SPICE客户端訪問客户機,你需要遵照#SPICE節中描述的步驟,通過該方式運行的客户機將支持與宿主機進行複製粘貼的操作。

SPICE[編輯 | 編輯原始碼]

One way to share the clipboard between the host and the guest is to enable the SPICE remote desktop protocol and access the client with a SPICE client. One needs to follow the steps described in #SPICE. A guest run this way will support copy paste with the host.

qemu-vdagent[編輯 | 編輯原始碼]

QEMU provides its own implementation of the spice vdagent chardev called qemu-vdagent. It interfaces with the spice-vdagent guest service and allows the guest and host share a clipboard.

To access this shared clipboard with QEMU's GTK display, you will need to compile QEMU from source with the --enable-gtk-clipboard configure parameter. It is sufficient to replace the installed qemu-ui-gtk package.

注意:
  • Feature request FS#79716 submitted to enable the functionality in the official package.
  • The shared clipboard in qemu-ui-gtk has been pushed back to experimental as it can freeze guests under certain circumstances. A fix has been proposed to solve the issue upstream.

Add the following QEMU command line arguments:

-device virtio-serial,packed=on,ioeventfd=on
-device virtserialport,name=com.redhat.spice.0,chardev=vdagent0
-chardev qemu-vdagent,id=vdagent0,name=vdagent,clipboard=on,mouse=off

These arguments are also valid if converted to libvirt form.

注意: While the spicevmc chardev will start the spice-vdagent service of the guest automatically, the qemu-vdagent chardev may not.

On linux guests, you may start the spice-vdagent.service user unit manually. On Windows guests, set the spice-agent startup type to automatic.

Windows專用説明[編輯 | 編輯原始碼]

QEMU可以運行從 Windows 95 至 Windows 11 的任何版本 Windows。

在QEMU中也可以運行 Windows PE

快速啟動設置[編輯 | 編輯原始碼]

注意: 改變電源設置需要一個 Administrtor 賬户

根據此論壇帖子所解釋的那樣,對於Windows8及之後的客户機最好在Control Panel的Power Options中禁用"Turn on fast startup (recommended)",該設置導致客户機在每次啟動時卡死。

為了正確應用對 -smp 選項進行的更改,可能也需要禁用快速啟動。

遠程桌面協議[編輯 | 編輯原始碼]

如果你使用一個 MS Windows 客户機,可能會想使用 RDP 連接到客户機 VM。若你正使用 VLAN 或與客户機處於同一個網絡中,先使用:

$ qemu-system-x86_64 -nographic -nic user,hostfwd=tcp::5555-:3389

接着通過 rdesktopfreerdp 連接到客户機。例如:

$ xfreerdp -g 2048x1152 localhost:5555 -z -x lan

在物理設備上克隆一個已安裝的Linux系統[編輯 | 編輯原始碼]

安裝在物理設備上的Linux系統可以克隆至QEMU VM中運行,參閱Clone Linux system from hardware for QEMU virtual machine

從 x86_64 環境中 Chroot 至 arm/arm64 環境[編輯 | 編輯原始碼]

有時候相比於在基於ARM架構的設備上工作,在磁盤鏡像上進行工作更容易。可以通過掛載一個root分區的SD卡/存儲設備,然後chroot到該設備實現該目的。

另一個使用 ARM chroot 的場景是在 x86_64 機器上構建 ARM 包。這種情況下,可以使用來自 Arch Linux ARM 的鏡像包來創建 chroot 環境 - 具體操作可查閱 [2]

無論哪種方式,都應該可以從chroot運行pacman並安裝更多軟件包,編譯大型庫等。由於可執行文件是針對ARM體系結構的,因此需要QEMU轉換為x86。 。

Install qemu-user-static on the x86_64 machine/host, and qemu-user-static-binfmt to register the qemu binaries to binfmt service.

在 x86_64 宿主機上安裝 binfmt-qemu-static,然後 qemu-user-static-binfmt 將負責 qemu 二進制文件註冊至 binfmt 服務的部分。

需要使用 qemu-user-static 執行其他架構上的程序,這個包與 qemu-emulators-full 提供的程序很相似,只是對於 chroot 來説必須使用 "static" 變種。比如:

qemu-arm-static path_to_sdcard/usr/bin/ls
qemu-aarch64-static path_to_sdcard/usr/bin/ls

這兩個命令分別用於執行 32 位 ARM 和 64ARM 的 {{ic|ls} }命令。注意如果沒有 chroot,這些都不會生效,因為那樣的話它們將會試圖尋找不存在宿主機系統上的一些二進制文件。

qemu-user-static 允許自動地用為 ARM 可執行文件添加 qemu-arm-staticqemu-aarch64-static 前綴。

檢查一下 ARM 可執行的支持是否被開啟了:

$ ls /proc/sys/fs/binfmt_misc
qemu-aarch64  qemu-arm	  qemu-cris  qemu-microblaze  qemu-mipsel  qemu-ppc64	    qemu-riscv64  qemu-sh4    qemu-sparc	qemu-sparc64  status
qemu-alpha    qemu-armeb  qemu-m68k  qemu-mips	      qemu-ppc	   qemu-ppc64abi32  qemu-s390x	  qemu-sh4eb  qemu-sparc32plus	register

每種可執行的文件都須在此處列出。

如果未開啟,請重啟 systemd-binfmt.service

將SD卡掛載至 /mnt/sdcard(設備名可能不同):

# mount --mkdir /dev/mmcblk0p2 /mnt/sdcard

如有需要,掛載啟動分區(同樣,使用合適的設備名):

# mount /dev/mmcblk0p1 /mnt/sdcard/boot

最後如Change root#Using chroot所描述的那樣,chroot 到 SD 卡的 root 中:

# chroot /mnt/sdcard /bin/bash

此外,可以使用 arch-install-scripts 提供的 arch-chroot 替代 chroot,可以方便地獲取網絡支持:

# arch-chroot /mnt/sdcard /bin/bash

還可以用 systemd-nspawn chroot 到 ARM 環境中:

# systemd-nspawn -D /mnt/sdcard -M myARMMachine --bind-ro=/etc/resolv.conf

--bind-ro=/etc/resolv.conf 是可選的,其在 chroot 中提供了一個可用的網絡 DNS。

處理常見問題[編輯 | 編輯原始碼]

本文或本章節可能需要合併到QEMU/Troubleshooting

附註: This section is long enough to be split into a dedicated subpage.(在 Talk:QEMU 中討論)

Not grabbing mouse input[編輯 | 編輯原始碼]

本文或本章節的語言、語法或風格需要改進。參考:Help:Style

原因:It is not explained what the option actually does. Is it causing or avoiding the side effect?(在Talk:QEMU討論)

Tablet mode has side effect of not grabbing mouse input in QEMU window:

-usb -device usb-tablet

It works with several -vga backends one of which is virtio.

鼠標指針抖動或者不穩定[編輯 | 編輯原始碼]

如果QEMU中鼠標指針不受控制地跳來跳去,那麼啟動QEMU之前在命令進行如下設置或許能解決該問題:

$ export SDL_VIDEO_X11_DGAMOUSE=0

如果成功了,可以把這條命令加入到你的 ~/.bashrc 文件中

看不見鼠標指針[編輯 | 編輯原始碼]

使用-show-cursor選項啟動QEMU以顯示指針。

如果這麼做不起作用的話,請確保你的顯示設備被正確設置了。例如: -vga qxl

還可嘗試 #鼠標整合 中提到的 -usb -device usb-tablet。該選項會覆蓋默認採用的PS/2鼠標仿真,將鼠標作為外設在宿主機和客户機之間同步指針位置。

有兩個不同的鼠標指針[編輯 | 編輯原始碼]

遵循 #鼠標整合 提到的方法。

使用 VNC 時鍵盤出現問題[編輯 | 編輯原始碼]

使用 VNC 時,您可能會遇到這裏所描述的鍵盤問題。 解決的方法是不使用 QEMU 的 -k 選項, 並使用 gtk-vncgvncviewer 。另請參見在libvirt郵件列表中發佈的消息

鍵盤像壞了一樣或者方向鍵不起作用[編輯 | 編輯原始碼]

如果發現某些鍵不起作用或按下一個按鍵,觸發的卻是其他按鍵,那麼你可能需要指定鍵盤佈局選項。在 /usr/share/qemu/keymaps 中可以找到鍵盤佈局選項。

$ qemu-system-x86_64 -k keymap disk_image

無法讀取鍵盤映射文件[編輯 | 編輯原始碼]

qemu-system-x86_64: -display vnc=0.0.0.0:0: could not read keymap file: 'en'

這類問題產生的原因是將非法的鍵盤映射名作為-k的參數傳遞給qemu。例如,en是錯誤的鍵盤映射名稱,en-us才是正確的。相關信息參見/usr/share/qemu/keymaps

客户機在調整窗口大小時一起被拉伸了[編輯 | 編輯原始碼]

按下 Ctrl+Alt+u 可以恢復到原來的大小。

ioctl(KVM_CREATE_VM) failed: 16 Device or resource busy[編輯 | 編輯原始碼]

如果在以 -enable-kvm 選項啟動QEMU時顯示了這樣一條錯誤信息:

ioctl(KVM_CREATE_VM) failed: 16 Device or resource busy
failed to initialize KVM: Device or resource busy

這意味着還有另一個 hypervisor 處於運行狀態, 不推薦同時運行多個hypervisor。

libgfapi 的錯誤信息[編輯 | 編輯原始碼]

啟動時若顯示如下錯誤信息:

Failed to open module: libgfapi.so.0: cannot open shared object file: No such file or directory

安裝 glusterfs 或者直接忽略這個錯誤信息,GlusterFS 只是一個可選的依賴。

LIVE-environments 上發生內核錯誤[編輯 | 編輯原始碼]

如果你啟動一個 live-environment(或者啟動一個系統),可能會遭遇如下錯誤:

[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown block(0,0)

或者其他阻礙啟動過程的東西(比如無法解包initramfs, 無法啟動foo服務之類的),試試啟動VM的時候用 -m VALUE 分配合適的 RAM 大小,如果內存太小是很有可能遭遇上述的問題的。

Windows 7 客户機的音頻質量差[編輯 | 編輯原始碼]

為Windows7使用 hda 音頻驅動可能造成音頻質量降低, 通過QEMU的 -soundhw ac97 參數選擇 ac97 作為音頻驅動, 並從Realtek AC'97 Audio Codecs下載AC97驅動,然後在客户機中安裝該驅動可能會解決這個問題。參見Red Hat Bugzilla – Bug 1176761以獲取更多信息。

Could not access KVM kernel module: Permission denied[編輯 | 編輯原始碼]

如果遇見了如下的錯誤信息:

libvirtError: internal error: process exited while connecting to monitor: Could not access KVM kernel module: Permission denied failed to initialize KVM: Permission denied

這是因為 Systemd 234 為 kvm 組註冊了一個動態ID (參見FS#54943)。可以編輯 /etc/libvirt/qemu.confgroup = "78" 改為 group = "kvm" 避免產生這個錯誤。

啟動 Windows VM 時產生 "System Thread Exception Not Handled"[編輯 | 編輯原始碼]

Windows 8或Windows 10 guest虛擬機在啟動時可能會引發通用兼容性異常,即「System Thread Exception Not Handled」,這通常是由實體機上舊版驅動程序的異常行為引起的。在KVM機器上,通常可以通過將CPU模型設置為 core2duo來解決此問題。

某些 Windows 遊戲/程序導致藍屏出現[編輯 | 編輯原始碼]

有時,一些能在物理機上正常運行的程序在虛擬機中會意外地崩潰。如果在以 root 運行 dmesg -wH 時發現有 MSR 相關的錯誤,則導致這些崩潰的原因是 KVM 注入了 GPF(General protection fault),當客户機嘗試訪問不受支持的寄存器(MSR, Model-specific registers)時會導致客户機上的應用程式崩潰。將 ignore_msrs=1 傳給 KVM 模塊可以使其忽略不支持的 MSR, 從而解決大部分的同類問題。

/etc/modprobe.d/kvm.conf
...
options kvm ignore_msrs=1
...

一些添加該選項可能會起作用的場景:

  • GeForce Experience 反映沒有可支持的CPU。
  • 星際爭霸2和黑色洛城使用 KMODE_EXCEPTION_NOT_HANDLED 對 Windows 10 的藍屏做了一些處理,藍屏信息中將無法識別驅動。
警吿: 雖然通常這麼做是安全的,對於某些應用程式也可能不起作用,但默默忽略未知的 MSR 仍可能破壞 VM 或其他 VM 中的其他軟件。

VM 中的應用程式有很高的延遲,或是需要等待很長的時間才會啟動[編輯 | 編輯原始碼]

本文內容或本節內容已經過期。

原因: No longer true since kernel 5.6 (在Talk:QEMU討論)

這可能是由於VM中的可用熵不足所致。考慮通過將 VirtIO RNG 設備添加到 VM,或安裝諸如 Haveged 之類的熵生成守護程序。

有趣的是,OpenSSH 需要一段時間才能在熵不足的情況下開始接受連接,而其日誌卻不會顯示原因。

中斷時間過長以及運行不流暢[編輯 | 編輯原始碼]

此問題表現為小停頓(斷斷續續),在圖形密集型應用程式(例如遊戲)中尤其明顯。

QXL 導致視頻解像度降低[編輯 | 編輯原始碼]

QEMU 4.1.0版本帶來了一個回退問題,當使用SPICE時,會將QXL視頻降到低解像度。 [3]例如,當KMS啟動時,文本解像度可能會低至4x10個字符。嘗試提高GUI解像度時,它可能會達到最低的支持解像度。

解決方法是,以這種形式創建設備:

-device qxl-vga,max_outputs=1...

使用啟用了安全啟動的OVMF時,VM無法啟動[編輯 | 編輯原始碼]

edk2-ovmf 中的 /usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.fd 是在 SMM 的支持下完成構建的,如果未在 VM 中禁用 S3 支持,則 VM 可能根本無法啟動。

在QEMU命令中添加 -global ICH9-LPC.disable_s3=1 以解決該問題。

參見 FS#59465 以及 https://github.com/tianocore/edk2/blob/master/OvmfPkg/README 獲取 QEMU 使用 Secure Boot 所需要的更多選項。

Virtual machine not booting into Arch ISO[編輯 | 編輯原始碼]

When trying to boot the virtual machine for the first time from an Arch ISO image, the boot process hangs. Adding console=ttyS0 to kernel boot options by pressing e in the boot menu you will get more boot messages and the following error:

:: Mounting '/dev/disk/by-label/ARCH_202204' to '/run/archiso/bootmnt'
Waiting 30 seconds for device /dev/disk/by-label/ARCH_202204 ...
ERROR: '/dev/disk/by-label/ARCH_202204' device did not show up after 30 seconds...
   Falling back to interactive prompt
   You can try to fix the problem manually, log out when you are finished
sh: can't access tty; job control turned off

The error message does not give a good clue as to what the real issue is. The problem is with the default 128MB of RAM that QEMU allocates to the virtual machine. Increasing the limit to 1024MB with -m 1024 solves the issue and lets the system boot. You can continue installing Arch Linux as usual after that. Once the installation is complete, the memory allocation for the virtual machine can be decreased. The need for 1024MB is due to RAM disk requirements and size of the installation media. See this message on the arch-releng mailing list and this forum thread.

客户機上的中斷沒有被觸發[編輯 | 編輯原始碼]

如果你是按照 OSDev Wiki 來編寫自己的作業系統,或者只是使用 QEMU 的 gdb 接口和 -s 標誌,您需要知道的是,很多仿真器(包括QEMU)通常會實現一些CPU中斷,同時還有許多硬件中斷沒有被實現。了解代碼是否觸發中斷的一種方法是使用:

-d int

可以在輸出中查看 interrupts/exceptions。

如要查看QEMU還提供了什麼客户機調試功能,使用如下命令:

qemu-system-x86_64 -d help

或者將 x86_64 替換為你選擇的其他架構

KDE with sddm does not start spice-vdagent at login automatically[編輯 | 編輯原始碼]

Remove or comment out X-GNOME-Autostart-Phase=WindowManager from /etc/xdg/autostart/spice-vdagent.desktop. [4]

Error starting domain: Requested operation is not valid: network 'default' is not active[編輯 | 編輯原始碼]

If for any reason the default network is deactivated, you will not be able to start any guest virtual machines which are configured to use the network. Your first attempt can be simply trying to start the network with virsh.

# virsh net-start default

For additional troubleshooting steps, see [5].

參閱[編輯 | 編輯原始碼]