QEMU - Arch Linux 中文维基

跳至內容

# QEMU

出自 Arch Linux 中文维基

相關文章

- Category:Hypervisors
- Libvirt
- QEMU/Guest graphics acceleration
- PCI passthrough via OVMF

翻譯狀態：

- 本文（或部分內容）譯自 QEMU，最近一次同步於 2024-11-22，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

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

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

作為虛擬機時，QEMU可以使用其他虛擬機管理程序（如 Xen 或 KVM）來使用 CPU 擴展（HVM）進行虛擬化，通過在主機 CPU 上直接執行客戶機代碼來獲得接近於宿主機的性能。

## 安裝

安裝 qemu-full包，(或 qemu-base包，一個無GUI支持的基本版本；qemu-desktop包，默認僅支持 x86_64 模擬）

並根據需要安裝下面的可選軟體包：

- qemu-block-gluster包 - Glusterfs 設備塊支持
- qemu-block-iscsi包 - iSCSI 設備塊支持
- samba包 - SMB/CIFS 伺服器支持

除了這些之外, 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-arm` 和 `qemu-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 的圖形前端

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

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

## 創建新虛擬系統

### 創建硬碟鏡像

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

原因： 如果我沒有理解錯手冊頁的話，原始格式只有在文件系統不支持「空洞」或者明確指定了預分配的情況下才會分配全部大小。參見 qemu-img(1) § NOTES。（在 [主站 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 鏡像。

用 `dd` 或 `fallocate` 也可以創建一個 raw 鏡像。

注意：您也可以通過 `dd` 或 `fallocate` 創建一個所需大小的 raw 鏡像。
警告：如果硬碟鏡像存儲在 Btrfs 系統上，則應在創建任何映像之前考慮禁用該目錄的 寫時複製 功能。可以在創建鏡像時為qcow2格式指定選項nocow：

    $ qemu-img create -f qcow2 image_file -o nocow=on 4G

#### Overlay存儲鏡像

你可以創建一次存儲鏡像（backing鏡像），然後讓 QEMU 只保存對backing鏡像的變更到一個overlay鏡像中。這能讓你恢復到這個存儲鏡像一開始的狀態。你可以在想還原時創建一個新的overlay鏡像，基於最初的backing鏡像。

要創建一個overlay鏡像，執行下面的命令。

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

之後，你可以正常運行 QEMU 虛擬機（參閱 #運行虛擬化的系統）：

    $ qemu-system-i386 img1.cow

基礎鏡像（指backing鏡像）會保持完好，對存儲內容的變更將被記錄在overlay鏡像文件中。

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

警告：基礎鏡像的絕對文件系統路徑存儲在（二進制的）覆寫鏡像文件中。若改變基礎鏡像的路徑，可能需要做一些調整。

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

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

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

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

#### 調整鏡像大小

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

執行 `qemu-img` 帶 `resize` 選項調整硬碟驅動鏡像的大小.它適用於 raw 和 qcow2. 例如, 增加鏡像 10 GiB 大小, 運行:

    $ qemu-img resize disk_image +10G

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

##### 減小鏡像大小

縮小磁碟映像時，必須首先在虛擬機中使用文件系統和分區工具減少分配的文件系統和分區大小，然後再減小磁碟鏡像。對於 Windows 虛擬機，可以從「控制面板-創建並格式化硬碟分區」中執行此操作。

警告：縮小磁碟鏡像而不減少虛擬機分區大小將導致數據丟失。

通過以下命令將磁碟鏡像減小 10 GiB：

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

#### 轉換鏡像格式

你可以使用 `qemu-img convert` 來調整鏡像格式. 例如，你可以使用一下命令來將 raw 格式的鏡像轉換成 qcow2 格式的鏡像:

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

這條命令不會刪除 input.img

### 準備安裝介質

要將作業系統安裝到您的磁碟鏡像, 你需要作業系統的安裝介質 (例如 光碟, 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-i386` 或 `qemu-system-x86_64`, 取決於客戶機架構)用來運行虛擬化的客戶機。用法是:

    $ qemu-system-i386 options disk_image

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

一般來說，如果一個選項有多個可能的值，你可以使用

    $ qemu-system-x86_64 option help

來列出所有可能的值。如果它支持屬性，你可以使用

    $ qemu-system-x86_64 option value,help

來列出所有可能的屬性。

例如:

    $ 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

你可以使用這些方法和 qemu(1) 的文檔來理解接下來幾個小節中的相關選項。

默認 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`。

### 以 UEFI 模式啟動

QEMU 使用的默認固件是 SeaBIOS，一個傳統 BIOS 的實現。QEMU 使用 `/usr/share/qemu/bios-256k.bin` (由 seabios包 提供) 作為默認的只讀 (ROM) 鏡像。你可以使用參數 `-bios` 來選擇另一個固件文件。然而， UEFI 需要可寫的內存來正常工作，所以你需要模擬 PC System Flash 。

OVMF 是一個為虛擬機提供 UEFI 支持的 TianoCore 項目。它可以通過 edk2-ovmf包 來安裝。

使用 OVMF 作為固件有兩種方法。第一種是複製 `/usr/share/edk2/x64/OVMF.4m.fd` 文件，使其可寫並用作 pflash 驅動器:

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

所有對 UEFI 設置的更改將直接保存到此文件中。

另一種更優選的方法是將 OVMF 分成兩個文件。第一個文件將是只讀的，並存儲固件可執行文件，而第二個文件用作可寫的變量存儲區。這樣做的好處是您可以直接使用固件文件，而無需複製，因此它會由 pacman 自動更新。

使用 `/usr/share/edk2/x64/OVMF_CODE.4m.fd` 作為第一個只讀 pflash 驅動器。複製 `/usr/share/edk2/x64/OVMF_VARS.4m.fd` ，使其可寫，並用作第二個可寫 pflash 驅動器:

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

如果需要啟用安全啟動，請使用q35機器類型，並將 `/usr/share/edk2/x64/OVMF_CODE.4m.fd` 替換為 `/usr/share/edk2/x64/OVMF_CODE.secboot.fd`。

### 可信平台模塊模擬

QEMU 可以模擬可信平台模塊 (Trusted Platform Module) ，這是某些系統（例如需要 TPM 2.0 的 Windows 11）所必需的。

安裝 swtpm包 ，來提供一個軟體 TPM 實現。創建一個目錄來存儲 TPM 數據 (這裡以 `/path/to/mytpm` 為例) 。 運行以下命令啟動模擬器r:

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

`/path/to/mytpm/swtpm-sock` 將由 swtpm 創建: 這是一個 UNIX 套接字，QEMU 將連接到此套接字。您可以將其放在任何目錄中。

默認情況下， swtpm 啟動一個 TPM 1.2 模擬器。 `--tpm2` 選項啟用 TPM 2.0 模擬。

最後，將以下選項添加到 QEMU:

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

然後 TPM 將在虛擬機內可用。關閉虛擬機後， swtpm 將自動終止。

有關更多信息，請參見 the QEMU documentation 。

如果虛擬機作業系統仍然無法識別 TPM 設備，請嘗試調整可能會導致該問題的 CPU 模型和拓撲選項。

## 宿主機和虛擬機數據交互

### 網絡

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

在默認情況下，用戶模式的客戶機能夠通過 10.0.2.2 這個IP訪問到宿主機。任何運行於宿主機上的服務端程序都可以通過這個地址被訪問到，比如說我們可以通過這個IP訪問到宿主機上的 SSH 伺服器或 SMB 伺服器。因此在這種情況下，客戶機能夠掛載宿主機通過 SMB 或 NFS 暴露出來的目錄，也可以訪問宿主機上的 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

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

原因：See Help:Style/Formatting and punctuation.（在Talk:QEMU討論）

virtiofsd包 提供了 virtiofsd 工具。有關可用選項的完整列表，請參閱在線文檔或 qemu-docs包 內置的 `/usr/share/doc/virtiofsd/README.md` 文件。

由於 qemu 程序需要訪問 virtiofsd 套接字，因此請將運行 qemu 的用戶添加到 'kvm' 用戶組。你可能需要重新登錄才能使更改生效。

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

原因： 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,

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

原因：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.

### 在宿主機上掛載客戶機的分區

在主機系統上掛載驅動器鏡像可能很有用，它可以作為在虛擬機和主機之間傳輸文件的一種方式。這應在虛擬機未運行時進行。

掛載驅動器的過程取決於 qemu 鏡像的類型 (raw 或 qcow2) 。我們將在 #掛載 raw 鏡像內的分區和 #掛載 qcow2 鏡像內的分區中詳細介紹兩種格式的掛載步驟。完整文檔請參見Wikibooks:QEMU/Images#Mounting an image on the host。

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

#### 掛載 raw 鏡像內的分區

可以通過將 raw 磁碟鏡像文件內的分區設置為環回設備來掛載這些分區。

##### 手動指出偏移量

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

    # 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.vmdk` 和 `file-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:minor` 將 `major:minor` 轉化為類似 `/dev/blockdevice` 的名字）。若要刪除創建的設備，請使用 `dmsetup remove qemu` 和 `losetup -d $loop`。

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

##### 使用線性 RAID

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

原因： CONFIG_MD_LINEAR Removal Linear RAID has been deprecated since 2021 and removed on Kernel Version 6.8. (在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

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

原因：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查找將無法進行。
提示：

- 使用此選項，虛擬機將使用 virtio 網絡驅動程序來進行用戶模式網絡： `-nic user,model=virtio-net-pci`.
- 使用此選項，用戶模式網絡將被隔離，與主機和外部網絡隔離開來：`-net user,restrict=y`.

### 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 -C /dev/null --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設備。

提示：

- 參見 Network bridge 獲取創建網橋的信息
- See https://wiki.qemu.org/Features/HelperNetworking for more information on QEMU's network helper.

首先，創建一個配置文件，包含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 [...]

#### 手工創建網橋

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

原因：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`，這可能是最常見的配置。這種配置使虛擬機看起來直接位於外部網絡，與物理主機位於同一以太網段。

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

- 安裝 bridge-utils包，它提供 `brctl` 來操作網橋。

- 啟用 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 wiki 和 Fedora 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 配置網絡

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

原因：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文檔了解更多的相關參數。

## 圖形

使用 `-display curses` 命令行選項，QEMU 可以模擬一個標準顯卡文本模式。這允許用戶可以直接在文本終端中直接輸入文本或看見文本輸出。 `-nographic` 選項起到了類似的作用。

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

### std

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

### qxl

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

在Linux客戶機中，需要加載 `qxl` 和 `bochs_drm` 這兩個內核模塊，以獲得一個比較好的效果。

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

### vmware

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

### virtio

`virtio-vga` / `virtio-gpu` 是一個基於virgl的3D並行虛擬化圖形驅動。目前它已經成熟；目前它僅支持Linux客戶機，且需要以`gallium-drivers=virgl`選項編譯mesa包。

若要在客戶機上啟用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 字符設備。`virtserialport` 的 `chardev=` 選項需要與 `chardev` 的 `id=` 相符，在本例中是 `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視頻驅動
- x-resizeAUR: 除 GNOME 之外的桌面環境在 SPICE 客戶端窗口大小調整時不會自動反應。此軟體包使用 udev 規則和 xrandr 為所有基於 X11 的桌面環境和窗口管理器實現自動調整大小。

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

### 開啟 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 sound

自 QEMU 8.2.0 版本開始，VirtIO 音效卡也可用。使用方式如下：

    -device virtio-sound-pci,audiodev=my_audiodev -audiodev alsa,id=my_audiodev

更多信息可以在 QEMU 文檔中找到。

## 安裝 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設備，必須在客戶端加載以下模塊：{`virtio`、`virtio_pci`、`virtio_blk`、`virtio_net`、`virtio_ring`。對於32位系統來說，不需要特定的「virtio」模塊。

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

    /etc/mkinitcpio.conf

    MODULES=(virtio virtio_blk virtio_pci virtio_net)

Virtio 磁碟公認的前綴為 `v`（例如：`vda`，`vdb`，等等）。因此，當從 virtio 磁碟啟動時，需要在 `/etc/fstab` 和 `/boot/grub/grub.cfg` 中進行更改。

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

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

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

### Windows 客戶機

#### Windows 的 Virtio 驅動

Windows 系統不自帶 virtio 驅動程序。最新和穩定版本的驅動程序由 Fedora 定期構建，有關下載驅動程序的詳細信息可以在 GitHub 上的 virtio-win 項目中找到。 在以下部分中，我們將主要使用由 virtio-win.iso 提供的穩定 ISO 文件。或者，可以使用 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）：

- 選擇選項加載驅動
- 反選隱藏與這個計算機硬體不兼容的驅動
- 按 瀏覽 按鈕並選擇 virtio iso 的 CDROM ，一般命名為 "virtio-win-XX"
- 然後瀏覽 `E:\viostor\[your-os]\amd64` ，選擇它並確認

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

##### 將現有的 Windows VM 轉為使用 virtio

可將現有的 Windows 客戶機改為從 virtio 磁碟中啟動，前提是客戶機中有 virtio 驅動，且該驅動在啟動期間就被加載。

然後我們需要讓 Windows 在 Windows 能以 virtio 模式啟動一個磁碟鏡像之前，在啟動時加載 virtio 驅動。

先創建一個新的磁碟鏡像，用於搜索 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 驅動

如果想要追蹤客戶機內存狀態（比如通過`virsh`的`dommemstat`命令）或者在運行時改變客戶機內存大小（儘管依然無法改變實際的內存大小，不過可以通過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，之後就可以通過 socat包、nmap包 或 openbsd-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-netcat包 或 gnu-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`.有關更多信息和標誌，請參閱 QEMU 文檔。
- 可以使用 `-smp cores=x,threads=y,sockets=1,maxcpus=z` 選項為虛擬機分配多個核心。threads 參數用於分配 SMT 核心。為 QEMU、管理程序和主機系統保留一個物理核心不受干擾是非常有益的。
- 檢查是否為虛擬機分配的足夠的內存。默認情況下，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 名稱`，在其中設置好 `args` 和 `haltcmd` 變量，配置示例：

    /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-host` 的 `hostdevice`屬性，語法為：

       -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客戶端的菜單而無法撤銷該操作，因為在輸入設備被重定向至虛擬機後，客戶端無法響應它們的操作。

#### 使用 udev 進行自動 USB 轉發

通常，轉發的設備必須在虛擬機啟動時可用才能被轉發。如果該設備斷開連接，它將不再被轉發。

您可以使用 udev rule 在設備上線時自動附加設備。在磁碟上的某個位置創建一個 `hostdev` 條目，並將其所有權 chown 為 root ，以防止其他用戶修改它。

    /usr/local/hostdev-mydevice.xml

    <hostdev mode='subsystem' type='usb'>
          <vendor id='0x03f0'/>
        <product id='0x4217'/>
    </hostdev>

然後創建一個用於附加或脫離設備的 udev 規則:

    /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"

詳閱這篇博客。

### 開啟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`選項的值。

### 自定義顯示器解析度

可以使用 `-device VGA,edid=on,xres=1280,yres=720` 來設置自定義顯示器解析度 (參見 EDID 和 display resolution) 。

### 複製和粘貼

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

#### SPICE

在主機和虛擬機之間共享剪貼板的一種方法是啟用 SPICE 遠程桌面協議，並使用 SPICE 客戶端訪問客戶端。

請按照 #SPICE 中描述的步驟進行。以這種方式運行的虛擬機將支持與主機的複製粘貼功能。

#### qemu-vdagent

QEMU 提供了其自己的 spice vdagent 字符設備實現，稱為 `qemu-vdagent`。它與 spice-vdagent 客戶端服務接口，可以實現虛擬機和主機之間的剪貼板共享。

要使用 QEMU 的 GTK 顯示器訪問此共享剪貼板，你需要從源碼編譯 QEMU ，並使用 `--enable-gtk-clipboard` 配置參數。這需要替換已安裝的 `qemu-ui-gtk` 包。

注意：

- 已提交功能請求 FS#79716 以在官方包中啟用此功能。
- 由於 在某些情況下會導致虛擬機凍結 ， qemu-ui-gtk 中的共享剪貼板功能已推回到實驗階段。上游已提出解決此問題的修複方案。

添加以下的 QEMU 命令行參數:

    -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

這些參數如果轉換為 libvirt 格式也是有效的。

注意：雖然 spicevmc 字符設備會自動啟動虛擬機的 spice-vdagent 服務，但 qemu-vdagent 字符設備可能不會。

在 Linux 虛擬機上，你可以手動啟動 `spice-vdagent.service` 用戶單元。在 Windows 虛擬機上，請將 spice-agent 的啟動類型設置為自動。

### 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

接著通過 rdesktop包 或 freerdp包 連接到客戶機。例如：

    $ 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。

在 x86_64 宿主機上安裝 qemu-user-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-static` 或 `qemu-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。

### 在 chroot 環境中使用 sudo

如果您在 chroot 環境中安裝了 sudo，並在嘗試使用它時收到以下錯誤：

    sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?

那麼您可能需要修改 binfmt 標誌，例如對於 aarch64：

    # cp /usr/lib/binfmt.d/qemu-aarch64-static.conf /etc/binfmt.d/
    # vi /etc/binfmt.d/qemu-aarch64-static.conf

並在該文件末尾添加一個 `C`：

    :qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64-static:FPC

然後重新啟動 systemd-binfmt.service 並檢查更改是否生效（注意標誌行上的 C）：

    # cat /proc/sys/fs/binfmt_misc/qemu-aarch64

    enabled
    interpreter /usr/bin/qemu-aarch64-static
    flags: POCF
    offset 0
    magic 7f454c460201010000000000000000000200b700
    mask ffffffffffffff00fffffffffffffffffeffffff

有關更多信息，請參閱內核 binfmt 文檔的「flags」部分。

## 處理常見問題

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

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

### Not grabbing mouse input

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

原因：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-vnc包 的 `gvncviewer` 。另請參見在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.conf` 將 `group = "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 需要一段時間才能在熵不足的情況下開始接受連接，而其日誌卻不會顯示原因。

### 中斷時間過長以及運行不流暢

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

- 原因之一是CPU的節能功能，該功能由CPU frequency scaling控制。請對所有處理器核心進行修改，將其更改為`performance`。
- 另一個可能的原因是PS/2輸入。從PS/2切換到Virtio輸入，請參閱PCI passthrough via OVMF#Passing keyboard/mouse via Evdev。

### QXL 導致視頻解析度降低

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

解決方法是，以這種形式創建設備：

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

### 使用啟用了安全啟動的OVMF時，VM無法啟動

edk2-ovmf包 中的 `OVMF_CODE.secboot.4m.fd` 以及 `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.

### 客戶機上的CPU中斷沒有被觸發

如果你是按照 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].

## 參閱

- Official QEMU website
- Official KVM website
- QEMU Emulator User Documentation
- QEMU Wikibook
- Hardware virtualization with QEMU by AlienBOB (last updated in 2008)
- Building a Virtual Army by Falconindy
- QEMU documentation
- QEMU on Windows
- Wikipedia
- Debian Wiki - QEMU
- QEMU Networking on gnome.org[失效連結 2022-09-22 ⓘ]
- Networking QEMU Virtual BSD Systems
- QEMU on gnu.org
- QEMU on FreeBSD as host
- Managing Virtual Machines with QEMU - openSUSE documentation
- Managing Virtual Machines with QEMU - openSUSE documentation
- KVM on IBM Knowledge Center

分類：​

- 使用已棄用source標籤的頁面
- 存在語法高亮錯誤的頁面
- 仿真
- 虛擬機管理
- 包含失效連結的頁面
- 使用「模板:風格」標記的頁面或章節
- 使用「模板:過時」標記的頁面或章節

隱藏分類：​

- 使用「模板:準確性」標記的頁面或章節
- 使用「模板:合併」標記的頁面或章節

QEMU
新增話題