QEMU

提供: ArchWiki
ナビゲーションに移動 検索に移動

関連記事

QEMU ホームページ より:

QEMU は汎用なオープンソースのマシンエミュレータ・バーチャライザーです。

マシンエミュレータとして使う場合、QEMU はあるマシン (例: ARM ボード) 用に作られた OS やプログラムを他のマシン (例: x86 PC) で動かすことができます。動的変換を利用することによって、素晴らしいパフォーマンスを実現します。

XenKVM など他のハイパーバイザを使うことで QEMU は仮想化のための CPU 拡張命令を利用することができます。バーチャライザーとして使う場合、ゲストコードをホスト CPU で直接実行することにより QEMU はネイティブに近いパフォーマンスを得ることができます。

目次

インストール

qemu-full パッケージ (または GUI が必要ない場合は qemu-base) をインストールしてください。また、任意で以下のパッケージもインストールしてください:

あるいは、ユーザーモードと静的のバリアントとして qemu-user-staticAUR が存在します。

QEMU バリアンツ

QEMUには、さまざまなユースケースに適したいくつかのバリアンツが用意されています。

最初の分類として、QEMUにはフルシステムエミュレーションモードとユーザーモードエミュレーションモードの2種類が提供されています。

フルシステムエミュレーション
このモードでは、QEMUは1つまたは複数のプロセッサとさまざまな周辺機器を含むフルシステムをエミュレートします。より正確ですが速度は遅く、エミュレートするOSはLinuxである必要がありません。
フルシステムエミュレーション用のQEMUコマンドは qemu-system-target_architecture という名前が付けられています。例えば インテル64ビットCPUのエミュレーション用の qemu-system-x86_64 、インテル32ビットCPU用の qemu-system-i386 、 ARM(32ビット)用の qemu-system-arm 、 ARM64用の qemu-system-aarch64 などです。
ターゲットアーキテクチャがホスト CPU と一致する場合、このモードでも KVM や Xen のようなハイパーバイザーを使うことで大幅なスピードアップの恩恵を受けられるかもしれません。
ユーザーモードエミュレーション
このモードでは、QEMUはホストシステムのリソースを利用することで、(潜在的に)異なるアーキテクチャ用にコンパイルされた Linux 実行ファイルを呼び出すことができます。互換性の問題がある場合があります。例えば、一部の機能が実装されていない、動的リンクされた実行ファイルがそのままでは動作しない(これについては#x86_64 から arm/arm64 環境への Chrootingを参照)、そして Linux のみがサポートされています(ただし Windows 実行ファイルの実行には Wine が使用できる場合があります)。
ユーザーモードエミュレーション用のQEMUコマンドには qemu-target_architecture という名前が付けられており、例えばintel 64ビットCPUのエミュレーション用は qemu-x86_64 になります。

QEMU には動的リンク型と静的リンク型のバリアンツが提供されています。

動的リンク型(デフォルト)
qemu-* コマンドはホストOSのライブラリに依存し、このため実行ファイルのサイズが小さくなっています。
静的リンク型
qemu-* コマンドは同じアーキテクチャの Linux システムにコピーすることができます。

Arch Linux の場合、フルシステムエミュレーションは以下のように提供されます:

非ヘッドレス (デフォルト)
このバリアントでは、追加の依存関係(SDL や GTK など)を必要とする GUI 機能を使用できます。
ヘッドレス
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.
  • 非公式の AUR パッケージ qemu-user-staticAUR は QEMU がサポートする全てのターゲットアーキテクチャにユーザーモードと静的バリアントを提供します。このパッケージのプリコンパイルバージョンが存在します: qemu-user-static-binAUR 。インストールされる QEMU コマンドは qemu-target_architecture-static という名前で、例えば intel 64-bit CPU 用は qemu-x86_64-static です。
  • 非公式の AUR パッケージ qemu-loongarch64-gitAUR は(qemu-system-loongarch64-gitAURqemu-loongarch64-static-gitAUR とともに) LoongArch アーキテクチャ用の QEMU で、version 7.1 から公式にサポートされています。
ノート: 現在のところ、Arch はフルシステムモードと静的リンクのバリアントを提供していません(公式にも AUR 経由でも)。これは通常は必要ないためです。

QEMUのグラフィカルフロントエンド

VirtualBoxVMware などの他の仮想化プログラムと違って、QEMUは仮想マシンを管理するためのGUI (仮想マシン実行時に表示されるウィンドウを除く)を提供せず、保存された設定を使って永続的な仮想マシンを作成する方法も提供しません。仮想マシンを起動するためのカスタムスクリプトを作成していない限り、仮想マシンを実行するためのすべてのパラメータは、起動のたびにコマンドラインで指定する必要があります。

Libvirt は、QEMU 仮想マシンを管理するための便利な方法を提供します。利用可能なフロントエンドについては、libvirtクライアントの一覧 を参照してください。

その他の QEMU 用 GUI フロントエンド:

  • AQEMU — Qt5で書かれたQEMU GUI。
https://github.com/tobimensch/aqemu || aqemuAUR

新しい仮想化システムの作成

ヒント: Arch Linux を仮想化する場合、既存の Arch Linux システム上に直接ディスクイメージを作成することができます、詳しくはインストールガイドを見て下さい。

ハードディスクイメージの作成

ヒント: QEMU イメージに関する詳細は QEMU Wikibook を参照。

CD-ROM やネットワークからライブシステムを起動するのでない (そしてオペレーティングシステムをハードディスクイメージにインストールしない) 限り、QEMU を実行するにはハードディスクイメージが必要になります。ハードディスクイメージはエミュレートするハードディスクの内容を保存するファイルです。

ハードディスクイメージを raw にすると、ゲストからは文字通りバイト単位で等しいようになり、ホスト上のゲストハードドライブをフルに使用することになります。この方法は I/O のオーバーヘッドを最小に抑えられますが、ゲストで使用していない領域もホストは使えないため、大量の容量を消費するのが欠点です。

また、ハードディスクイメージを qcow2 などのフォーマットにすることもできます。ゲストオペレーティングシステムが実際に仮想ハードディスク上のセクタに書き込んだ時にイメージファイルに容量を割り当てます。ホストシステムで占める容量はかなり少なくて済み、ゲストオペレーションにはフルサイズのイメージとして見えます。QEMU のスナップショット機能にも対応しています (詳しくは#モニタコンソールを使ってスナップショットを作成・管理を参照)。こちらの形式では raw と違ってパフォーマンスに多少影響を与えます。

QEMU にはハードディスクイメージを作成するための qemu-img コマンドがあります。例えば raw フォーマットで 4GiB イメージを作成するには:

$ qemu-img create -f raw image_file 4G

-f qcow2 を使うことで qcow2 ディスクを作成できます。

ノート: raw イメージは ddfallocate を使って必要なサイズのファイルを作成するだけでも作れます。
警告: ハードディスクイメージを Btrfs ファイルシステム上に保存する場合、イメージを作成する前にディレクトリの Copy-on-Write を無効にするべきでしょう。

オーバーレイストレージイメージ

一度ストレージメディアを作成してから ('backing' イメージ)、QEMU にイメージへの変更を overlay イメージとして維持させることができます。これによってストレージメディアを前の状態に戻すことが可能になります。戻りたい時点で、オリジナルの backing イメージを元に新しい overlay イメージを作成することで戻すことができます。

overlay イメージを作成するには、次のようにコマンドを実行してください:

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

その後通常通り QEMU VM を起動することができます (仮想化システムを実行するを参照):

$ qemu-system-x86_64 img1.cow

backing イメージには変更が加えられず、ストレージへの追記は overlay イメージファイルに保存されるようになります。

backing イメージのパスが変更された場合、修正が必要になります。

警告: backing イメージの絶対ファイルシステムパスは (バイナリの) overlay イメージファイルに保存されます。backing イメージのパスを変更するのは大変です。

オリジナルの backing イメージのパスからこのイメージに繋がるようにしてください。必要ならば、オリジナルのパスに新しいパスへのシンボリックリンクを作成します。次のようなコマンドを実行してください:

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

あなたの判断で、backing イメージの古いパスがチェックされない'危険な' rebase を実行することもできます:

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

イメージのリサイズ

警告: NTFS ブートファイルシステムを含んでいるイメージをリサイズするとそこにインストールされている VM が起動できなくなってしまう可能性があります。詳しい説明や回避方法は ここ を見て下さい。

qemu-img 実行可能ファイルには resize オプションがあり、ハードドライブイメージの簡単なリサイズができます。このコマンドは rawqcow2 の両方で使えます。例えば、イメージ容量を 10GB 増やすには、次を実行してください:

$ qemu-img resize disk_image +10G

ディスクイメージを拡大した後、仮想マシン内でファイルシステムおよびパーティションツールを使用して、新しいスペースを実際に使い始める必要があります。ディスクイメージを縮小する場合、仮想マシン内のファイルシステムおよびパーティションツールを使用して まず割り当てられたファイル・システムとパーティション・サイズを縮小 し、それに応じてディスクイメージを縮小する必要があります。Windows ゲストの場合、"ハードディスクパーティションの作成とフォーマット" コントロールパネルを開きます。

ヒント: NTFS ブートファイルシステムを含んでいるイメージをリサイズする方法 (この例では qcow2 フォーマットのイメージを使っていますが他のフォーマットでも方法は同じです):

重要: イメージを使用している VM はあらかじめ全てシャットダウンしてください。

リサイズするのに qcow2 から raw にイメージを変換する必要はありません (ただしイメージが NTFS で VM ゲストをそこから起動している場合は別です)。直接 qemu-img resize コマンドを使って下さい。その後、ゲストの仮想マシンを起動してディスクに新しい場所を再配置してください。

そして適当なツールを使ってパーティションのサイズを変更 (例えば Windows Vista 以降なら、Windows を起動して初めから入っている Disk Management ユーティリティ を使うことができます)。

イメージが起動する NTFS の場合、qcow2 ファイルを以下のようにして変換する必要があります:

イメージを raw フォーマットに変換して末尾に空きスペースを追加します (オリジナルのイメージはバックアップとして残しておく):

$ qemu-img convert -f qcow2 -O raw myimg.qcow2 myimg.raw
$ truncate -s +4G myimg.raw
$ mv myimg.qcow2 myimg.qcow2.bak

大きくしたイメージを qcow2 に戻して、raw は削除:

$ qemu-img convert -f raw -O qcow2 myimg.raw myimg.qcow2 
$ rm myimg.raw 

オリジナルのイメージのパーミッションと合わせる:

$ chown --reference=myimg.qcow2.bak myimg.qcow2
$ chmod --reference=myimg.qcow2.bak myimg.qcow2

インストールメディアを準備する

ディスクイメージにオペレーティングシステムをインストールするには、オペレーティングシステムのインストールメディア (例: オプティカルディスク、USB ドライブ、ISO イメージ) が必要です。QEMU はメディアに直接アクセスできないのでインストールメディアをマウントしてはいけません。

ヒント: 光ディスクを使う場合、最初に中身をファイルに移動させると良いでしょう。パフォーマンスが発揮されるようになり、デバイスに直接アクセスする必要がなくなります (従って、メディアのデバイスファイルのアクセス権限を変えることなく QEMU を通常ユーザーで起動することが可能になります)。 例えば、 CD-ROM デバイスノードの名前が /dev/cdrom なら、次のコマンドでファイルに dump することが出来ます:
$ dd if=/dev/cdrom of=cd_image.iso bs=4k

オペレーティングシステムのインストール

ここで初めてエミュレータを起動することになります。ディスクイメージにオペレーティングをインストールするには、ディスクイメージとインストールメディアの両方を仮想マシンに結びつけて、インストールメディアから起動するようにする必要があります。

例えば i386 ゲストで、CD-ROM としてのブータブル ISO ファイルと raw ディスクイメージからインストールするには:

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

他のメディアタイプ(フロッピー、ディスクイメージ、物理ドライブなど)の読み込みについては qemu(1) を、その他の便利なオプションについては #仮想化システムを実行する を見て下さい。

オペレーティングシステムのインストールが終了したら、直接 QEMU イメージを起動することができます( #仮想化システムを実行する を参照)。

{注意|デフォルトではマシンに割り当てられるメモリは 128MiB だけです。メモリの量は -m スイッチで調整できます。例えば -m 512M-m 2G 。}

ヒント:
  • 少なくとも設定中や実験中は、 -boot order=x を指定する代わりにブートメニュー: -boot menu=on を使う方が快適だと感じるユーザもいるかもしれません。
  • QEMUをヘッドレスモードで実行する場合、QEMU はデフォルトでポート5900でローカルVNCサーバを起動します。ゲストOSへの接続に TigerVNC を使用することができます: vncviewer :5900
  • インストールプロセスでフロッピーや CD を替える必要がある場合、QEMU マシンモニター (仮想マシンのウィンドウで Ctrl+Alt+2 を押す) を使って仮想マシンからストレージデバイスを取り外したりアタッチすることができます。ブロックデバイスを見るには info block を、デバイスをスワップアウトするには change コマンドを使って下さい。Ctrl+Alt+1 を押せば仮想マシンに戻ります。

仮想化システムを実行する

qemu-system-* バイナリ (例えば qemu-system-i386qemu-system-x86_64 など、エミュレートするアーキテクチャによって異なります) を使って仮想化システムを実行します。使用方法は:

$ qemu-system-x86_64 options disk_image

全ての qemu-system-* バイナリでオプションは共通です、全てのオプションのドキュメントは qemu(1) を見て下さい。

デフォルトで、QEMU は仮想マシンのビデオ出力をウィンドウに表示します。注意: QEMU ウィンドウの中をクリックすると、マウスポインタが取り込まれます。ポインタを戻すには、Ctrl+Alt+g を押して下さい。

警告: QEMU を root で実行しないでください。スクリプト内で root で実行する必要があるときは、-runas オプションを使って QEMU の root 特権を外して下さい。

KVM を有効にする

使用しているプロセッサとカーネルが KVM をサポートしている必要があります。また、必要なカーネルモジュールがロードされてなければなりません。詳しくは KVM を見て下さい。

QEMU を KVM モードで起動するには、起動オプションに -enable-kvm を追加してください。実行中の仮想マシンで KVM が有効になっているかどうか確認するには、Ctrl+Alt+Shift+2 を使って QEMU Monitor に入り、info kvm と入力してください。

ノート:
  • -machine オプションの引数 accel=kvm-enable-kvm または -accel kvm オプションと同等です。
  • CPU モデル host は KVM を必要とします。
  • GUI ツールを使って VM を起動した時にパフォーマンスが出ない場合、KVM サポートを確認してください。QEMU がソフトウェアエミュレーションにフォールバックしている可能性があります。
  • ブルースクリーンを出さずに Windows 7 や Windows 8 を正しく起動するには KVM を有効にする必要があります。

IOMMU (Intel VT-d/AMD-Vi) サポートを有効にする

IOMMU を使うことで PCI パススルーやメモリの保護などの機能が利用できます。Wikipedia:ja:IOMMU#利点Memory Management (computer programming): Could you explain IOMMU in plain English? を見てください。

IOMMU を有効化するには:

  1. CPU によって AMD-Vi/Intel VT-d がサポートされていること、BIOS の設定で有効になっていることを確認してください。
  2. Intel の CPU を使っている場合は intel_iommu=on、AMD の CPU を使っている場合は amd_iommu=onカーネルパラメータに追加してください。
  3. PCI パススルーのためだけに IOMMU が必要な場合、iommu=pt パラメータも追加してください。Linux がパススルーするデバイスの IOMMU だけを有効化できるようになり、システムの他のデバイスへのパフォーマンスの影響を避けられます。CPU メーカー別のパラメータ (上記) も on にする必要があります。
  4. 再起動して dmesgDMAR があることを確認して IOMMU が有効になっていることをチェックしてください: [0.000000] DMAR: IOMMU enabled
  5. -device intel-iommu を追加して IOMMU デバイスを作成してください:
$ qemu-system-x86_64 -enable-kvm -machine q35,accel=kvm -device intel-iommu -cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time ..
ノート: 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
(vfio-pci による PCI パススルーなど) IO をリマップするには intel_iommu=on カーネルパラメータの追加が必要ですが、PCI パススルーを使う場合は -device intel-iommu は設定してはいけません。

UEFIモードでの起動

QEMU が使用するデフォルトのファームウェアは SeaBIOS で、これはレガシー BIOS の実装です。QEMU はデフォルトの読み取り専用(ROM)イメージとして /usr/share/qemu/bios-256k.bin (seabios で提供される) を使用します。他のファームウェアファイルを選択するには -bios 引数を使用します。しかし、UEFI が正しく動作するためには書き込み可能なメモリが必要であるため、代わりに PC システムフラッシュ をエミュレートする必要があります。

OVMF は仮想マシンの UEFI サポートを有効にするための TianoCore プロジェクトです。 edk2-ovmf パッケージで インストール することができます。

OVMF をファームウェアとして使うには 2 つの方法があります。一つは /usr/share/edk2-ovmf/x64/OVMF.fd をコピーして書き込み可能にし、pflashドライブとして利用する方法です:

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

UEFI 設定への全ての変更はこのファイルに直接保存されます。

もう一つのより好ましい方法は OVMF を二つのファイルに分割することです。最初のファイルは読み込み専用でファームウェアの実行ファイルを保存し、2番目のファイルは書き込み可能な変数ストアとして使われます。利点はファームウェアファイルをコピーせずに直接使うことができ、 pacman によって自動的にアップデートされることです。

/usr/share/edk2-ovmf/x64/OVMF_CODE.fd を最初のリードオンリーな pflash ドライブとして使用します。/usr/share/edk2-ovmf/x64/OVMF_VARS.fd をコピーして書き込み可能にし、2台目の書き込み可能な pflash ドライブとして使用します:

-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

Trusted Platform Module のエミュレーション

QEMUは、Windows 11などの一部のシステムで必要とされるTrusted Platform Module をエミュレートすることができます。

ソフトウェア TPM の実装を提供する swtpm パッケージをインストール します。 TPM のデータを格納するディレクトリを作成します(/path/to/mytpmを例として使用します)。以下のコマンドを実行し、エミュレータを起動します:

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

/path/to/mytpm/swtpm-sockswtpm が作成します: これはQEMUが接続するUNIXソケットです。どのディレクトリに置いてもかまいません。

デフォルトでは、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

すると、VM 内で TPM が使用できるようになります。VM をシャットダウンすると、swtpmは自動的に終了します。

詳しくは the QEMU documentation を参照してください。

ホスト・ゲスト OS 間でデータを移動する

ネットワーク

ファイルを転送できるネットワークプロトコルであれば NFS, SMB, NBD, HTTP, FTP, SSH など何でも使ってホストとゲスト OS 間でデータを共有することができます、ただしネットワークを適切に設定して適切なサービスを有効にする必要があります。

デフォルトのユーザーモードネットワークは IP アドレス 10.0.2.2 でゲストがホスト OS にアクセスするのを許可します。ホスト OS で動作する全てのサーバー、SSH サーバーや SMB サーバーなどは、この IP アドレスでアクセスすることが可能になります。そしてゲストでは、SMBNFS でホストのディレクトリをマウントしたり、ホストの HTTP サーバーなどにアクセスすることが可能です。 ゲスト OS で動作しているサーバーにホスト OS がアクセスすることはできませんが、他のネットワーク設定を使えば不可能ではありません (#QEMU の Tap ネットワーク を参照)。

QEMUのポートフォワーディング

QEMUのポートフォワーディングはIPv4のみです。

ノート: QEMUのポートフォワーディングは IPv4 のみです。IPv6 ポート転送は実装されておらず、最後のパッチは 2018 年に提案されました [1]

QEMUはホストからゲストへポートを転送し、例えばホストからゲスト上で動作しているSSHサーバーへの接続を可能にします。

例えば、ホストのポート 60022 とゲストのポート 22(SSH) をバインドするには、次のようなコマンドでQEMUを起動します:

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

ゲストで sshd が動いていることを確認し、接続します:

$ ssh guest-user@127.0.0.1 -p 60022

SSHFS を使って共有読み込みと書き込みのためにゲストのファイルシステムをホストにマウントできます。

複数のポートを転送するには、hostfwd-nic 引数で繰り返すだけです、例えば VNC のポートは次のようになります:

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

QEMUの内蔵SMBサーバ

QEMUのドキュメントには "内蔵の" SMBサーバーがあると書かれていますが、実際は tmp/qemu-smb.ランダムな文字列 にある自動生成の smb= で共有設定できるのは1つのディレクトリだけですが、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 のように共有オプションを複数回使用した場合、最後に定義したものだけが共有されます。
  • ゲストシステムがWindowsで共有フォルダにアクセスできない場合、NetBIOSプロトコルが有効になっているかどうか とNetBIOSプロトコルが使用する ポート がファイアウォールでブロックされていないか確認してください。
  • 共有フォルダーにアクセスできず、ゲストシステムがWindows 10 Enterprise または Education、Windows Server 2016 の場合、ゲストアクセスを有効にします
  • #Tap networking with QEMU を使用する場合、 SMB を取得するには -device virtio-net,netdev=vmnic -netdev user,id=vmnic,smb=shared_dir_path を使います。

複数のディレクトリを共有し、仮想マシンの実行中にディレクトリの追加や削除を行う方法として、空のディレクトリを共有し、共有ディレクトリ内のディレクトリへのシンボリックリンクを作成/削除する方法があります。これを機能させるには、実行中の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 を使う

https://wiki.qemu.org/Documentation/9psetup QEMU ドキュメント] を参照してください。

virtiofsd によるホストファイル共有

virtiofsd は QEMU パッケージに同梱されています。 virtiofsd は QEMU パッケージと一緒に出荷されます。 ドキュメントは オンライン または /usr/share/doc/qemu/tools/virtiofsd.html が QEMU がインストールされたローカルファイルシステムで入手できます。

virtiofsd ソケットにアクセスする必要があるため、qemu を実行するユーザを 'kvm' グループに追加します。変更を反映するにはログアウトする必要があるかもしれません。

virtiofsd を root で起動します:

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

ここで

  • /var/run/qemu-vm-001.sock はソケットファイルです。
  • /tmp/vm-001 はホストとゲスト vm の共有ディレクトリです。

作成されたソケットファイルは root のみアクセス権を持っています。以下のようにグループ kvm にアクセス権を与えます:

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

VM起動時に以下の設定オプションを追加します:

-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

ここで

  • size=4G-m 4G オプションで指定したサイズと一致する必要があります。
  • /var/run/qemu-vm-001.sock は先に起動されたソケットファイルを指します。

ゲストでは共有が有効となるように設定されている必要があることに注意してください。 Windows の場合、手順書 があります。一度設定すると、Windows の Z: ドライブに共有ディレクトリの内容が自動的にマップされます。

以下のものがあれば、Windows 10 ゲストシステムは適切に設定されています。

  • VirtioFSSService windows サービス
  • WinFsp.Launcher windows サービス
  • Windows の"デバイスマネージャー"の"システムデバイス"の下の VirtIO FS Device driver

上記がインストールされていても Z: ドライブが表示されない場合は、Windowsのプログラムの追加と削除から"Virtio-win-guest-tools"を修復してみてください。

ゲストのパーティションをホストにマウントする

ホストシステムの下にドライブイメージをマウントすると、ゲストへのファイルの出し入れに便利な場合があります。これは仮想マシンが動作していないときに行う必要があります。

ホストにドライブをマウントする手順は、qemu イメージの rawqcow2 といった種類によって異なります。この2つの形式のドライブをマウントする手順については、#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 から始まり最後まで続くループバックデバイスをセットアップします。そしてこのループバックデバイスがマウントされます。パーティションの正確なサイズを指定するために sizelimit オプションを使うこともできますが、これは通常は不要です。

ディスクイメージによっては、必要なパーティションがオフセット32256で始まらないかもしれません。fdisk は開始と終了のオフセットを 512 バイトのセクタで示しますので、512 倍して mount に渡すべき正しいオフセットを求めてください。 ディスクイメージによって、必要なパーティションがオフセット 32256 から始まってない可能性があります。 fdisk -l disk_image を実行してイメージ内のパーティションを見て下さい。fdisk は512バイトセクタ単位で起点と終点を表示するので、512 を掛けて適当なオフセットを mount で指定してください。

loop モジュールでパーティションを自動検出する

Linuxの loop ドライバは、実際にはループバックデバイスのパーティションをサポートしていますが、デフォルトでは無効になっています。有効にするには、以下のようにしてください:

  • ループバックデバイスを全て取り除いてください (マウントされているイメージをすべてアンマウントするなど)。
  • loop カーネルモジュールを アンロード し、 max_part=15 パラメータを設定してロードしてください。また、loop デバイスの最大数は max_loop パラメータで制御できます。
ヒント: 毎回 max_part=15 で loop モジュールをロードするには、カーネルに loop.ko モジュールが組み込まれているかどうかにあわせて、 /etc/modprobe.d にエントリを記述するか、カーネルコマンドラインに loop.max_part=15 と記述します。

イメージをループバックデバイスとして設定:

# losetup -f -P disk_image

これで、作成されたデバイスが /dev/loop0 の場合、追加のデバイス /dev/loop0pX が自動的に作成されます。X はパーティションの番号です。これらのパーティションのループバックデバイスは直接マウントすることができます。例えば:

# mount /dev/loop0p1 mountpoint

udisksctl でディスクイメージをマウントする方法は Udisks#ループデバイスのマウント を参照してください。

kpartxを使う

multipath-tools パッケージの kpartx はデバイス上のパーティションテーブルを読み込んでパーティションごとに新しいデバイスを作成することができます。例えば:

# kpartx -a disk_image

これでループバックデバイスがセットアップされ、/dev/mapper/ に必要なパーティションデバイスが作成されます。

qcow2 イメージからパーティションをマウントする

NBD (network block device) プロトコルを使ってディスクイメージを共有することができる qemu-nbd を使用してみます。

まず、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

qcow2 イメージの中にパーティションをマウントする

qcow2 イメージの中のパーティションは qemu-nbd を使ってマウントできます。Wikibooks を見て下さい。

実際のパーティションをハードディスクイメージのシングルプライマリパーティションとして使う

場合によって、QEMU の中からシステムパーティションのどれかを使いたくなることもあるでしょう。仮想マシンでの raw パーティションの使用は、読み書きの操作が物理ホストのファイルシステムレイヤーを通過しないため、パフォーマンスが高くなります。そのようなパーティションをホストとゲストでのデータの共有手段として使うこともできます。

Arch Linux では、raw パーティションのデバイスファイルは、デフォルトで、rootdisk グループが所有者です。root 以外のユーザーで raw パーティションに読み書きできるようにしたい場合は、パーティションのデバイスファイルの所有者をそのユーザーに変えるか、そのユーザーをdiskグループに追加するか、ACL を使用してより詳細なアクセス制御を行う必要があります。

警告:
  • 仮想マシンにホストシステムのクリティカルなデータ (root パーティションなど) を変更する許可を与えるのは可能ではありますが、推奨はされません。
  • ホストとゲストの両方で同時にパーティションのファイルシステムを読み書き可能でマウントしてはいけません。そうすると、データが破壊される可能性があります。

その後、パーティションを QEMU の仮想マシンに仮想ディスクとしてアタッチできます。

ただし、仮想マシン全体をパーティションに収めたいときは、事態は多少複雑になります。そのような場合、実際に仮想マシンを起動するディスクイメージファイルがないために、MBR でパーティション分けされたデバイスではなくファイルシステムとしてフォーマットされたパーティションにブートローダーをインストールすることができません。このような仮想マシンは次のいずれかの方法でブートできます: #カーネルと initrd を手動で指定する#MBR で仮想ディスクをシミュレートする#device-mapper を使う#リニア RAID を使う、または#ネットワークブロックデバイスを使う

カーネルと initrd を手動で指定する

QEMU は GRUB などのブートローダーを迂回して、Linux カーネルinit ramdisk を直接ロードすることをサポートしています。それから root ファイルシステムを含んでいる物理パーティションで、パーティションされていない仮想ディスクとして起動することができます。以下のようなコマンドを実行することで行います:

ノート: この例で使用するのはゲストのイメージではなく、ホストのイメージです。ゲストのイメージを使いたい場合は、(ホストからファイルシステムを保護するために) /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

上の例では、ゲストの root ファイルシステムに使われている物理パーティションはホストの /dev/sda3 で、ゲストでは /dev/sda として表示されます。

もちろん、Arch Linux で使われているものとは違うカーネルや initrd を自由に指定することができます。

複数のカーネルパラメータ-append オプションで指定するときは、クォートを使って囲む必要があります。例:

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

MBR で仮想ディスクをシミュレートする

ファイルシステムでフォーマットされたパーティションを維持しながらゲストのパーティションをまるでディスクであるかのようなパーティションにしないで、仮想マシンで物理パーティションを使用するもっと複雑な方法として、MBR をシミュレートして GRUB などのブートローダーを使って起動できるようにする方法があります。

次の例では、マウントされていないプレーンな テンプレート:Ic/dev/hda''N' パーティションがあり、その中に QEMU ディスクイメージの一部にしたいファイルシステムがあるとします。秘訣は、 QEMU rawディスクイメージに組み込みたい実パーティションに、動的にマスターブートレコード (MBR) を付加することです。より一般的には、このパーティションは、より大きなシミュレートされたディスクの任意の部分、特に元の物理ディスクをシミュレートしますが テンプレート:Ic/dev/hda''N' だけを仮想マシンに公開するブロックデバイスにすることができます。

このタイプの仮想ディスクは、MBRとパーティションへの参照(コピー)を含む VMDK ファイルで表すことができますが、 QEMU はこの VMDK フォーマットをサポートしていません。たとえば、 以下のように作成された 仮想ディスクは

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

以下のエラーメッセージとともに QEMU によって拒否されます

Unsupported image type 'partitionedDevice'

VBoxManagefile.vmdkfile-pt.vmdk の2つのファイルを作成します。後者は MBR のコピーであり、テキスト・ファイル file.vmdk が参照します。ターゲットパーティションまたは MBR の外側への読取り操作にはゼロが返され、書き込まれたデータは破棄されます。

device-mapper を使う

VMDK ディスクリプタ・ファイルを利用するのと同様の方法で、 device-mapper を利用して、 MBR ファイルに付属するループ・デバイスを対象パーティションにプリペンドする方法があります。仮想ディスクのサイズがオリジナルと同じである必要がない場合、まずMBRを保持するためのファイルを作成します。

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

これで、最新のディスクパーティションツールが使用するパーティションアライメントポリシーに従った 1 MiB (2048*512バイト) のファイルが作成されます。古いパーティショニングソフトウェアとの互換性のために、2048セクタではなく63セクタが必要になる場合があります。MBR に必要なブロックは 512 バイトのみです。追加の空き領域は BIOS ブートパーティションや、ハイブリッドパーティショニングスキームの場合は GUID パーティションテーブルに使用できます。次に、ループデバイスを MBR ファイルにアタッチします:

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

この例では、結果のデバイスは /dev/loop0 です。device mapper を使って MBR とパーティションを結合します:

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

生成された /dev/mapper/qemu は、 QEMU の raw ディスクイメージとして使用します。仮想ディスク上にパーティションテーブル(例としてリニア 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 によって作成された VDMK 記述子ファイル内のテーブルと同様のフォーマットを持ち、代わりに dmsetup create qemu--tabletable_file でファイルからロードできます。仮想マシンには /dev/hdaN だけがアクセス可能で、ハードディスクの残りはゼロとして読み取られ、書き込まれたデータは最初のセクタを除いて破棄されます。 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 が MBR パーティションテーブルを使用する唯一のオペレーティングシステムであり、同じコンピュータにインストールされた最新のオペレーティングシステムは GUID パーティションテーブルを使用できます)の場合です。Windows XP はハードウェアプロファイルをサポートしているため、同じインストールを異なるハードウェア構成で交互に使用できます(この場合はベアメタルと仮想)。Windows は新しく検出されたハードウェアのドライバをプロファイルごとに1回だけインストールする必要があります。この例ではコピーされた MBR のブートローダコードを更新して、元のシステムに存在するマルチブート対応のブートローダ(GRUB など)を起動するのではなく、 /dev/hdaN から直接 Windows XP をロードする必要があることに注意してください。または、ブートローダインストールを含むブートパーティションのコピーを MBR と同じ方法で仮想ディスクに含めることもできます。

リニア RAID を使う

リニアモードのソフトウェア RAID (linear.ko カーネルドライバが必要です)とループバックデバイスを使うこともできます:

最初に、MBRを保持する小さなファイルを作成します:

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

これで 16 KB (32 * 512 バイト) のファイルが作成されます。(MBR は512バイトのブロックしか必要としませんが) あまり小さくしすぎないことが重要です。なぜならファイルを小さくすればするほど、ソフトウェア RAID デバイスのチャンクサイズも小さくしなくてはならなくなり、パフォーマンスに影響を与えるからです。次に、MBR ファイルのループバックデバイスを設定します:

# losetup -f /path/to/mbr

他にループバックを使っていないために、作成されるデバイスは /dev/loop0 になるとします。次のステップはソフトウェア RAID を使って "merged" MBR + /dev/hdaN ディスクイメージを作成することです:

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

作成した /dev/md0 は QEMU の raw ディスクイメージとして使用します (エミュレータがアクセスできるようにパーミッションを設定するのを忘れないでください)。最後にプライマリパーティションの開始位置が /dev/md0/dev/hdaN に一致するようにディスクの設定 (ディスクのジオメトリとパーティションテーブルの設定) を行います (上の例では 16 * 512 = 16384 バイトのオフセットです)。ホストマシンで fdisk を使って行ってください。エミュレータの中で行ってはいけません: QEMU のデフォルトのディスク認識ルーチンによってキロバイトで割り切れないオフセットが生まれるとソフトウェア RAID コードで管理できなくなります。ホストから以下を実行してください:

# fdisk /dev/md0

X を押してエキスパートメニューを開きます。トラック毎のセクタ数を設定してシリンダーの容量が MBR ファイルの容量に一致するようにしてください。ヘッダが2つでセクタサイズが512の場合、1トラックあたりのセクタ数は16となり、シリンダのサイズは 2x16x512=16k になります。

R を押してメインメニューに戻って下さい。

P を押してシリンダーのサイズが 16k になってることを確認します。

/dev/hdaN にあわせてシングルプライマリパーティションを作成してください。パーティションの開始位置はシリンダー2で終了位置はディスクの末尾になります (シリンダーの数は fdisk に入力したときの値で変わります)。

最後に、結果をファイルに書き出してください ('w')。これでホストから直接パーティションをディスクイメージとしてマウントすることができます:

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

もちろん、元のパーティション /dev/hdaN に必要ツールが含まれていれば、QEMU を使ってディスクイメージにブートローダーを設定できます。

ネットワークブロックデバイスを使う

Network Block Device によって、Linux はリモートサーバをブロックデバイスの1つとして使うことができます。 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.1 という拡張子が重要です。他は変えてもかまいません。上記のスクリプトを実行後 (nbd-server がパーティションにアクセスできるように root で実行してください)、以下のコマンドで QEMU を起動できます:

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

ネットワーク

仮想ネットワークのパフォーマンスはユーザーモードネットワークまたは vde によるよりも tap デバイスやブリッジを用いる方が良いでしょう。tap デバイスやブリッジはカーネル内で実装されているからです。

加えて、デフォルトの e1000 NIC のエミュレーションではなく virtio ネットワークデバイスを仮想マシンに指定することでネットワークのパフォーマンスを向上させることができます。詳しくは #virtio ドライバーのインストール を参照。

リンク層アドレス

QEMU に -net nic 引数を与えると、デフォルトで、仮想マシンにリンク層アドレス 52:54:00:12:34:56 のネットワークインターフェイスが割り当てられます。しかしながら、ブリッジネットワークで複数の仮想マシンを使用する場合、個別の仮想マシンにはタップデバイスの仮想マシン側からそれぞれ固有のリンク層 (MAC) アドレスを設定しなくてはなりません。設定を行わないと、ブリッジが上手く動きません。同一のリンク層アドレスを持つ複数のソースからパケットを受け取ることになるからです。たとえタップデバイス自体に固有のリンク層アドレスを設定していたとしても、ソースのリンク層アドレスはタップデバイスを通過するときに書き換えられないため、問題が発生します。

個々の仮想マシンに固有のリンク層アドレスを設定、それも、どのアドレスも 52:54: で始まるように設定してください。以下のオプションを使って下さい (X は任意の16進数の数字に置き換えてください):

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

固有のリンク層アドレスの生成は複数の方法で行うことができます:

1. NIC ごとに固有のリンク層アドレスを手動で指定する。仮想マシンを起動するたびに同じ IP アドレスが DHCP サーバーによって割り当てられるという利点がありますが、仮想マシンが大量にある場合は現実的ではありません。

2. 仮想マシンを起動するたびにランダムなリンク層アドレスを生成する。衝突する可能性はほとんどゼロですが、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

3. 以下のスクリプト qemu-mac-hasher.py を使ってハッシュ関数を利用し仮想マシンの名前からリンク層アドレスを生成する。仮想マシンの名前を一意なものとして、上記の方法の良いところを組み合わせています。スクリプトが実行されるたびに同一のリンク層アドレスが生成される上、衝突する可能性はほとんどありません。

qemu-mac-hasher.py
#!/usr/bin/env python

import sys
import zlib

if len(sys.argv) != 2:
    print("usage: %s <VM Name>" % sys.argv[0])
    sys.exit(1)

crc = zlib.crc32(sys.argv[1].encode("utf-8")) & 0xffffffff
crc = str(hex(crc))[2:]
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: 外部 icmpv6 はまだサポートされていません。IPv6 アドレスへの Ping は動作しません。

ホストがインターネットに接続されていれば、このデフォルトの設定で簡単に仮想マシンをインターネットにアクセスさせることができますが、外部ネットワークからは仮想マシンは直接は見えず、また、複数の仮想マシンを同時に起動していても仮想マシン同士が通信することはできません。

QEMU のユーザーモードネットワークには内蔵の TFTP や SMB サーバー、ゲストを VLAN に追加してゲストの通信を可能にするなどの機能があります。詳しくは -net user フラグの QEMU ドキュメントを参照してください。

ただし、ユーザーモードネットワークには有用性とパフォーマンスの両方で制約があります。より高度なネットワーク設定をするには tap デバイスや他の方法を使って下さい。

ノート: ホスト環境が systemd-networkd を使用している場合、systemd-networkd#必要なサービスと設定に書かれているように /etc/resolv.conf ファイルのシンボリックリンクを作成してください。作成しないとゲスト環境で DNS ルックアップができなくなります。
ヒント: ユーザーモードネットワークで virtio ドライバーを使用するためのオプションは次の通りです: -nic user,model=virtio-net-pci

QEMU の Tap ネットワーク

Tap デバイスは Linux カーネルの機能で、本当のネットワークインターフェイスのように見える仮想ネットワークインターフェイスを作成することができます。tap インターフェイスに送られたパケットは、そのインターフェイスに bind された、QEMU などのユーザースペースプログラムに送信されます。

QEMU は仮想マシンで tap ネットワークを利用して、tap インターフェイスに送られたパケットを仮想マシンに送信することで仮想マシンのネットワークインターフェイス (通常は Ethernet インターフェイス) から受け取ったように見せることが可能です。逆に、仮想マシンがネットワークインターフェイスを通して送信したものは全て tap インターフェイスが受け取ります。

Tap デバイスは Linux の bridge ドライバーによってサポートされているため、tap デバイスを互いに、または eth0 といったホストのインターフェイスとブリッジすることができます。これは、仮想マシンを互いに通信できるようにしたい場合や、LAN 上の他のマシンが仮想マシンに通信できるようにしたい場合に価値があります。

警告: tap デバイスとホストのインターフェイス (eth0 など) をブリッジすると、仮想マシンは外部ネットワークから直接認識されるようになり、攻撃を受ける可能性が出てきます。仮想マシンからアクセスできるリソースに応じて、通常のコンピュータと同じような対策を施して仮想マシンを防護するようにしてください。仮想マシンのリソースがほとんどなかったり複数の仮想マシンを立ち上げるなど危険性が高すぎる場合、ホストオンリーネットワークを使って NAT を設定するほうが良いでしょう。その場合、ゲストごとにファイアウォールを設定する必要はなく、ホストだけにファイアウォールを設定すれば十分です。

ホストオンリーネットワーク

ブリッジに IP アドレスが与えられていてそこへのトラフィックが許可されていながら、本当のインターフェイス (例: eth0) がブリッジに接続されていない場合、仮想マシンは互いに通信したりホストシステムと通信することができるようになります。しかしながら、物理ホストで IP マスカレードを設定しないかぎり外部ネットワークとは一切通信することができません。この設定は VirtualBox などの他の仮想化ソフトウェアではホストオンリーネットワークと呼ばれています。

ヒント:
  • IP マスカレードを設定したい場合、インターネット共有#NAT の有効化ページを見てください。
  • ブリッジインターフェイスで DHCP サーバーを実行して仮想ネットワークを構築することもできます。例えば 172.20.0.1/16 サブネットで DHCP サーバーとして dnsmasq を使うには:
# 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 アドレスを与えずにブリッジへの全てのトラフィックを INPUT チェインで drop する iptables ルールを追加した場合、仮想マシンは互いに通信することはできても、物理ホストや外側のネットワークに接続できなくなります。この設定は 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
...

/etc/qemu/パーミッション755 であることを確認してください。そうでない場合、 QEMU の問題GNS3 の問題 が発生する可能性があります。

次に VM を起動します; デフォルトのネットワークヘルパーとデフォルトのブリッジ br0 で QEMU を実行する最も基本的な使い方は:

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

ブリッジ br1 と virtio ドライバを使用するには:

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

ブリッジを手動で作成する

ヒント: QEMU 1.1 から、スクリプトを追加することなく network bridge helper で tun/tap を設定することができます。#qemu-bridge-helper を使用するブリッジネットワーク を参照。

以下では仮想マシンを eth0 などのホストインターフェイスにブリッジする方法を説明しています。おそらく一番よく使われている設定です。この設定では、物理的なホストマシンと同一の Ethernet セグメントに、直接外部ネットワークに仮想マシンが位置するようになります。

通常の Ethernet アダプタをブリッジアダプタで置き換えて、通常の Ethernet アダプタをブリッジアダプタに bind することにします。

  • ブリッジを制御するための brctl が入っている bridge-utils をインストール。
  • IPv4 フォワーディングを有効にする:
# sysctl -w net.ipv4.ip_forward=1

変更を永続的にするために、/etc/sysctl.d/99-sysctl.confnet.ipv4.ip_forward = 0net.ipv4.ip_forward = 1 に変えます。

  • tun モジュールをロードして起動時にロードするように設定してください。詳しくはカーネルモジュールを参照。
  • オプションでブリッジを作成します。詳細は netctl でブリッジ接続 を参照してください。ブリッジに br0 という名前を付けるか、以下のスクリプトをブリッジの名前に変更してください。以下の run-qemu スクリプトでは、リストにない場合は br0 が設定されます。これは、デフォルトではホストがブリッジを介してネットワークにアクセスしていないと想定されているからです。
/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 用に root:kvm 750 パーミッションで /etc/qemu-ifdown の tap アダプタを落とすスクリプトを作成:
/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 enp | 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

すぐに変更を適用するには sysctl -p /etc/sysctl.d/10-disable-firewall-on-bridge.conf を実行してください。

libvirt wikiFedora bug 512206 を参照。起動中にファイルが存在しないというエラーが起こるときは、起動時に bridge モジュールをロードするようにしてください。カーネルモジュール#systemd を参照。

または、次のようにルールを追加することで全てのトラフィックをブリッジで通すように iptables を設定することができます:

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

iptables による物理デバイスと Tap デバイスのネットワーク共有

この記事あるいはセクションは インターネット共有 と合併することが議論されています。
ノート: 重複、QEMUに特化したものではありません。 (議論: トーク:QEMU#)

ブリッジネットワークは、有線インターフェイス (eth0 など) 間では正常に動作し、セットアップも簡単です。ただし、ホストがワイヤレスデバイスを介してネットワークに接続されている場合、ブリッジはできません。

参考として ネットワークブリッジ#ブリッジ上の無線インターフェイス を参照。

これを克服する1つの方法は、tap デバイスに静的 IP を設定し、linux に自動的にルーティングを処理させ、iptables ルールで tap インターフェイスとネットワークに接続されたデバイス間のトラフィックを転送することです。

参考として インターネット共有 を参照。

tap や tun など、デバイス間でネットワークを共有するために必要なものを見つけることができます。次に、必要なホスト構成のヒントを示します。上記の例で示したように、クライアントは、tap インターフェイスに割り当てられた IP をゲートウェイとして、静的 IP を設定する必要があります。注意点は、DNS サーバーがネットワークに接続されているホストデバイスから別のホストデバイスに変更された場合は、クライアント上の 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つのデバイスが、1つの内部デバイスとトラフィックを共有していると仮定しています。例えば次のようなものです:

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

上記は、tap デバイスとの有線および無線接続の共有を可能にする転送を示しています。

示されている転送ルールはステートレスであり、純粋な転送のためのものです。特定のトラフィックを制限し、ゲストや他の人を保護するためにファイアウォールを設置することを考えることができます。しかし、これらはネットワークパフォーマンスを低下させますが、シンプルなブリッジにはそのようなものはありません。

おまけ: 接続が有線または無線のいずれであっても、tun デバイスを使用してリモートサイトに VPN 経由で接続された場合、その接続用にオープンされた tun デバイスが tun0 であり、事前のiptablesルールが適用されていると仮定すると、リモート接続もゲストと共有されます。これにより、ゲストも VPN 接続をオープンする必要がなくなります。繰り返しますが、ゲストネットワークは静的である必要があるため、この方法でホストをリモート接続する場合、おそらくゲスト上の DNS サーバーを編集する必要あります。

VDE2 によるネットワーク

VDE とは?

VDE は Virtual Distributed Ethernet の略です。uml_switch の拡張として始まりました。仮想ネットワークを管理するためのツールボックスです。

基本的にはソケットである仮想スイッチを作成して、物理マシンと仮想マシンを両方ともスイッチに"接続"するという考えになります。以下で説明する設定はとてもシンプルです。ただし、VDE はさらに強力な力を持っており、仮想スイッチ同士を接続したり、別のホストでスイッチを動作させスイッチのトラフィックを監視することなどができます。プロジェクトのドキュメント を読むことを推奨。

この方法の利点はユーザーに sudo 権限を与える必要がないということです。通常ユーザーに modprobe の実行を許可する必要はありません。

基本

VDE サポートは vde2 パッケージでインストールできます。

この設定では、tun/tap を使ってホストに仮想インターフェイスを作成します。tun モジュールをロード (詳しくはカーネルモジュールを参照):

# 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 [...]

物理ネットワークでやるのと同じようにゲストのネットワークを設定してください。

ヒント: 仮想マシンからインターネットにアクセスするためにタップデバイスに NAT を設定することができます。詳しくはインターネット共有#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 "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE

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

        # Kill VDE switch
        pgrep -f 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 が実行できるようにパーミッションを変更:

# chmod u+x /etc/systemd/scripts/qemu-network-env

通常の方法で起動することができます (詳しくは systemd#ユニットを使う を参照):

# systemctl start qemu-network-env

他の方法

上の方法が動作しない場合やカーネル設定, 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 Bridge

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 でカスタム Ethernet プロファイルを使います:

/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-device を結合することもできます。たとえば、次のような引数は:

-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= で作成されたことに注意してください。-nic パラメータの前半は -netdev パラメータですが、後半 (model= の後) はデバイスに関連付けられています。同じパラメータ (たとえば、 smb= ) が使用されます。ネットワークを完全に無効にするには、 -nic none を使用します。

使用できるパラメーターの詳細については、 QEMU ネットワークのドキュメント を参照してください。

グラフィックカード

QEMU は -curses コマンド・ライン・オプションを使用して、標準のグラフィックカードのテキストモードをエミュレートできます。これにより、テキストターミナル内でテキストを入力しテキスト出力を直接見ることができます。代わりに、 -nographic も同様の目的を果たします。

QEMU はいくつかのタイプの VGA カードをエミュレートできます。カードタイプは -vgatype コマンドラインオプションで渡され、 std, qxl, vmware, virtio, cirrus または none のいずれかになります。

std

-vga std では 2560 x 1600 ピクセルまでの解像度を得ることができます。QEMU 2.2 からデフォルトとなっています。

qxl

QXL は、2D サポートのある準仮想化グラフィックスドライバーです。これを使用するには、-vga qxl オプションを渡して、ゲストにドライバーをインストールしてください。QXL を使用する場合、グラフィックのパフォーマンスを向上させるために #SPICE を使用するとよいでしょう。

Linux ゲストでは、適切なパフォーマンスを得るために qxlbochs_drm カーネルモジュールをロードしてください。

QXL デバイスのデフォルトの VGA メモリサイズは 16M です。これは QHD(2560x1440) までの解像度を駆動するのに十分です。より高い解像度を有効にするには、 vga_memmb を増やします

vmware

多少バグが存在しますが、std や cirrus よりもパフォーマンスが上です。Arch Linux ゲスト用の VMware ドライバー xf86-video-vmwarexf86-input-vmmouse をインストールします。

virtio

virtio-vga / virtio-gpuvirgl ベースの準仮想化 3D グラフィックスドライバです。現在開発中で、オプション galla-drivers=virgl でコンパイルされた mesa (>=11.2) を持つごく最近 (>=4.4) のLinuxゲストのみをサポートしています。

ゲストシステムで 3D アクセラレーションを有効にするには、-device virtio-vga-gl でこの vga を選択し、ディスプレイデバイスで sdl および gtk ディスプレイ出力に対してそれぞれ -display sdl,gl=on または -display gtk,gl=on を使用して OpenGL コンテキストを有効にします。ゲスト側のカーネルログを見ることで設定が問題ないか確認できます:

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

cirrus

cirrus グラフィカルアダプタは 2.2 以前まではデフォルト でした。新しいシステムでは 使用しないほうがよい とされています。

none

これは VGA カードが全くない PC と同じようになります。-vnc オプションを使ってもアクセスすることはできません。また、QEMU に VGA カードをエミュレートさせ SDL ディスプレイを無効にする -nographic オプションとは異なります。

SPICE

SPICE プロジェクト は、仮想マシンへのリモートアクセスをシームレスに行うための完全なオープンソースソリューションを提供することを目的としています。

ホストで 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=on は spice チャネルを待ち受ける TCP ポート 5930 を設定し、クライアントが認証なしで接続できるようにします
    ヒント: TCP ポートの代わりに wikipedia:Unix_socket Unix ソケット を使用すると、ホストシステムでネットワークスタックを使用する必要が無くなります。ネットワークと関連プロトコルを使用するためにパケットをカプセル化したりカプセル化を解除することもありません。ソケットはハードドライブ上の i ノードによってのみ識別されます。したがって、パフォーマンス的にはこちらの方が優れていると考えられています。代わりに -spice unix=on,addr=/tmp/vm_spice.socket,disable-ticketing=on を使用します。
  3. -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 は virtio-serial デバイスの spice vdagent 用のポートを開きます。
  4. -chardev spicevmc,id=spicechannel0,name=vdagent は、そのポートに spicevmc の chardev を追加します。virtserialport デバイスの chardev= オプションが、chardev オプション (この例では {ic spicechannel0}}) に指定された id= オプションと一致することが重要です。また、ポート名が 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その他のクライアント セクションを参照してください。

SPICE クライアントを手動で実行する

Unix ソケット /tmp/vm_spice.socket で待ち受けるゲストに接続する方法の1つは、望みのクライアントに応じて $remote-viewer spice+unix:///tmp/vm_spice.socket または $spicy--uri="spice+unix:///tmp/vm_spice.socket" を使用して SPICE クライアントを手動で実行することです。SPICE モードの QEMU はリモートデスクトップサーバーのように振る舞うため、-daemonize パラメータを指定してデーモンモードで 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 、ポート 5930 で示されるゲストの SPICE サーバへ転送しています。 コマンド sleep 10 をバックグラウンドで実行するよう ssh に要求する -f オプションに注意してください。このようにして、ssh セッションはクライアントがアクティブな間実行され、クライアントが終了すると自動的に閉じます。

QEMU で SPICE クライアントを実行する

ディスプレイが -display spice-app パラメータを使用して SPICE に設定されている場合、QEMU は適切なソケットで SPICE クライアントを自動的に起動できます。これは、XDG MIME Applications#mimeapps.list mimeapps.list ファイルによって決定されたシステムのデフォルト SPICE クライアントをビューアとして使用します。

ゲストで SPICE サポートを有効にする

Arch Linux ゲスト では、マルチモニタまたはクリップボード共有のサポートを改善するために、以下のパッケージをインストールする必要があります:

  • spice-vdagent: クライアントと X-session などとの間でコピー&ペーストを可能にする Spice エージェント xorg クライアント。
  • xf86-video-qxl: Xorg X11 qxl ビデオドライバ

その他のオペレーティングシステム のゲストについては、spice-space downloadゲスト セクションを参照してください。

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 サーバに接続するためのパスワードを要求するようになります。

SPICE による TLS 暗号化通信

SPICE サーバと通信するために TLS 暗号化を設定することもできます。まず、次のファイルを含むディレクトリを作成する必要があります(名前は指定されたとおりでなければなりません):

  • ca-cert.pem: CA マスター証明書。
  • server-cert.pem: ca-cert.pem で署名されたサーバ証明書。
  • server-key.pem: サーバの秘密キー。

Spice User Manual に、サーバ用に独自に作成した認証局で自己署名証明書を生成する例が示されています。

その後、上記の説明と同様に SPICE を使用して QEMU を実行しますが、-spice 引数として: -spice tls-port=5901,password=yourpassword,x509-dir=/path/to/pki_certs を使用します。、/path/to/pki_certs は、前述の3つの必要なファイルを含むディレクトリのパスとなります。

これで、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サーバー設定では、いかなる形式の認証も使用されません。どのユーザーもどのホストからでも接続できます。

基本的なパスワード認証

アクセスパスワードは password オプションを使用して簡単に設定できます。QEMU モニターでパスワードを指定する必要があり、パスワードが提供された場合にのみ接続が可能になります。

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

QEMU モニターでは、change vnc password コマンドを使用してパスワードを設定し、次にパスワードを指定します。

次のコマンドラインは、直接 vnc をパスワードを付きで実行します。

$ printf "change vnc password\n%s\n" MYPASSWORD | qemu-system-x86_64 -vnc :0,password -monitor stdio
ノート: パスワードは 8 文字までに制限されており、総当たり攻撃で推測できます。パブリックネットワークではより厳重に保護することを強く推奨します。

オーディオ

オーディオバックエンドを作成する

-audiodev フラグは、ホスト上のオーディオバックエンドドライバとそのオプションを設定します。使用可能なオーディオバックエンドドライバとそのオプション設定のリストについては qemu(1) のマニュアルページに詳細があります。

最低限、オーディオバックエンドを選択し、PulseAudio の ID を設定する必要があります。たとえば:

-audiodev pa,id=snd0

オーディオバックエンドを使用する

Intel HD Audio

Intel HD Audio エミュレーションの場合は、コントローラーとコーデックデバイスの両方を追加してください。使用可能なインテル 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 をエミュレートします。
  • ゲストマシン用のビデオグラフィックカードでエミュレートされたドライバも音質の問題を引き起こす可能性があります。1つずつテストして動作させてください。qemu-system-x86_64-h | grep vga} で可能なオプションを一覧できます。

virtio ドライバーのインストール

QEMU は virtio ドライバを使って準仮想化ブロックデバイスとネットワークデバイスを使用する機能をゲストに提供し、より良いパフォーマンスとより低いオーバーヘッドを実現します。

  • virtio ブロックデバイスは、ディスクイメージを渡すためのオプション -drive と、パラメータ if=virtio を必要とします:
$ qemu-system-x86_64 -drive file=disk_image,if=virtio
  • ネットワークでもほぼ同じです:
$ qemu-system-x86_64 -nic user,model=virtio-net-pci
ノート: これはゲストマシンが virtio デバイス用のドライバーを持っている場合にのみ機能します。Arch Linux を含む Linux には必要なドライバーが入っていますが、他のオペレーティングシステムで virtio デバイスが機能する保証はありません。

Arch Linux ゲストを用意する

Arch Linux ゲストをインストールした後 virtio デバイスを使うには、次のモジュールをゲストでロードする必要があります: virtio, virtio_pci, virtio_blk, virtio_net, virtio_ring。32ビットゲストの場合、特定の "virtio" モジュールは必要ありません。

virtio ディスクから起動したい場合、イニシャル ramdisk に必要なモジュールを含める必要があります。デフォルトでは、mkinitcpioautodetect フックによって管理されています。もしくは /etc/mkinitcpio.confMODULES 配列を使用して必要なモジュールを組み込み、イニシャル 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 コマンドのサポートを得ることができます。

Windows ゲストを用意する

Windows 用の virtio ドライバ

Windows には virtio ドライバは付属していません。最新の安定版バージョンのドライバはFedoraによって定期的にビルドされており、ドライバのダウンロードの詳細は virtio-win on GitHub で提供されています。以降のセクションでは、ここで提供されている安定版 ISO ファイル virtio-win.iso を主に使用します。または、virtio-winAUR を使用します。

ブロックデバイスドライバ

Windows の新規インストール

インストール時にドライバをロードする必要があります。手順としては、プライマリディスクデバイスおよび Windows ISO インストールメディアとともに cdrom デバイスで virtio ドライバを含む ISO イメージをロードします。

$ 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 インストーラが "Where do you want to install Windows?" と尋ねる段階で、ディスクを見つけられないという警告が表示されます。以下の手順に従ってください (アップデート適用済みの Windows Server 2012 R2 がベース):

  • Load Drivers オプションを選択。
  • Hide drivers that are not compatible with this computer's hardware のチェックを外す。
  • Browse ボタンをクリックして virtio iso の CDROM を開く。通常 "virtio-win-XX" という名前になります。
  • E:\viostor\[your-os]\amd64 を選択して OK を押す。

これで virtio ディスクが表示されるので、選択して、フォーマット・インストールすることができます。

virtio を使用するように既存の Windows VM を変更する

virtio ディスクから起動するように既存の Windows ゲストを変更するには、起動時にゲストによって virtio ドライバがロードされる必要があります。 そのため、virtio モードでディスクイメージを起動できるようにする前に、起動時に virtio ドライバーをロードするように Windows に教える必要があります。

このためには、まず virtio モードで接続される新しいディスクイメージを作成し、ドライバの検索をトリガします:

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

ブートディスクは IDE モードのまま、フェイクディスクを virtio モード、ドライバ ISO イメージを使用して元の Windows ゲストを実行します。

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

Windows はフェイクディスクを検出して適切なドライバを探します。失敗した場合は、デバイスマネージャ に移動し、感嘆符アイコン(開いているはず)が表示されている SCSI ドライブを探し、ドライバの更新 をクリックして仮想 CD-ROM を選択します。CD-ROM 内のドライバフォルダに移動せず、単に CD-ROM ドライブを選択するだけで、Windows は適切なドライバを自動的に検索します (Windows 7 SP1 でテスト済み)。

Windows に次回起動時にセーフモードで起動するように要求します。これは、Windows の msconfig.exe ツールを使用して行うことができます。セーフモードでは新しい virtio ドライバを含むすべてのドライバが起動時にロードされます。Windows は、起動時に virtio ドライバが必要であることを認識すると、将来の起動のためにそれを記憶します。

セーフモードで起動するように指示されたら、仮想マシンをオフにして再度起動できます。今度の起動ディスクは virtio モードで接続されています:

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

virtio ドライバがロードされた状態のセーフモードで起動されているはずです。これで msconfig.exe に戻り、セーフモードでの起動を無効にして、Windows を再起動できます。

ノート: if=virtio パラメータを使用してブルースクリーン・オブ・デスに遭遇した場合、virtio ディスクドライバがインストールされていないか、起動時にロードされていない可能性があります。セーフモードで再起動し、ドライバの構成を確認してください。

ネットワークドライバ

virtio ネットワークドライバーのインストールは少し簡単で、単に -nic 引数を追加するだけです。

$ qemu-system-x86_64 -m 4G -drive file=windows_disk_image,if=virtio -nic user,model=virtio-net-pci -cdrom virtio-win.iso

ネットワークアダプタが検出され、そのドライバが検索されます。失敗した場合は、デバイスマネージャ に移動し、感嘆符アイコン(開いているはず)が表示されているネットワークアダプタを探し、ドライバの更新 をクリックして仮想 CD-ROM を選択してください。ディレクトリを再帰的に検索するチェックボックスを選択することを忘れないでください。

バルーンドライバ

(virsh コマンドの dommemstat などで) ゲストのメモリ状態を追跡したり実行時にゲストのメモリサイズを変えたい場合 (メモリサイズは変更できませんが、バルーンドライバを膨張させることでメモリ使用量を制限できます) 、ゲストにバルーンドライバをインストールする必要があります。

このためには、デバイス マネージャー にアクセスし、システム デバイス (またはほかのデバイス から認識されない PCI コントローラ) で PCI 標準 RAM コントローラ を検索し、ドライバの更新 を選択してください。ウィンドウが開いたら コンピュータを参照して... を選択し、CD-ROM を選択してください(そして サブフォルダーも検索する チェックボックスを忘れないでください)。インストール後に再起動してください。これによりドライバがインストールされ、バルーンを膨らませることができます (たとえば hmp コマンド balloon memory_size によって、バルーンはゲストの使用可能なメモリサイズを memory_size に縮小するために可能な限り多くのメモリを消費します)。しかし、それでもゲストのメモリ状態を追跡することはできません。これを行うには Balloon サービスを正しくインストールする必要があります。管理者としてコマンドラインを開いて、CD-ROM から Balloon ディレクトリに移動し、システムとアーキテクチャに応じてさらに深く移動してください。amd64 (x86) ディレクトリまで移動したら blnsrv.exe -i を実行するとインストールが実行されます。その後 virsh コマンド dommemstat はサポートされているすべての値を出力するはずです。

FreeBSD ゲストを用意する

FreeBSD 8.3 以降を使っている場合は emulators/virtio-kmod port をインストールしてください、10.0-CURRENT ではカーネルに含まれています。インストール後、/boot/loader.conf ファイルに以下を追加します:

virtio_loader="YES"
virtio_pci_load="YES"
virtio_blk_load="YES"
if_vtnet_load="YES"
virtio_balloon_load="YES"

そして次を実行して /etc/fstab を修正してください:

sed -i bak "s/ada/vtbd/g" /etc/fstab

それから /etc/fstab が問題ないか確認してください。何かがおかしい場合、レスキュー CD で起動して /etc/fstab.bak/etc/fstab にコピーします。

QEMU モニタ

QEMU の実行中、実行中の仮想マシンと対話するためのいくつかの方法を提供するために、モニタコンソールが提供されます。QEMU モニタは、現在の仮想マシンに関する情報の取得、デバイスのホットプラグ、仮想マシンの現在の状態のスナップショットの作成など、興味深い機能を提供します。すべてのコマンドのリストを表示するには、QEMU モニタコンソールで help または ? を実行するか、QEMU 公式ドキュメント の関連セクションを参照してください。

モニタコンソールにアクセスする

グラフィカルビュー

デフォルトグラフィックオプションの std を使用している場合、QEMU ウィンドウで Ctrl+Alt+2 を押すか、View > compatmonitor0 をクリックすることで QEMU モニタにアクセスできます。仮想マシンのグラフィカルビューに戻るには、Ctrl+Alt+1 を押すか、View > VGA をクリックします。

ただし、モニタにアクセスする標準的な方法は必ずしも便利ではなく、QEMU がサポートするすべてのグラフィック出力で機能するわけではありません。

Telnet

telnet を有効にするには、-monitor telnet:127.0.0.1:port,server,nowait パラメータを指定して QEMU を実行してください。仮想マシンが起動すると、telnet 経由でモニタにアクセスできるようになります:

$ telnet 127.0.0.1 port
ノート: リッスンする IP として 127.0.0.1 を指定した場合、QEMU が動作しているのと同じホストからのみモニタに接続できるようになります。リモートホストから接続したい場合、0.0.0.0 をリッスンするよう次のようにQEMU に指示する必要があります: -monitor telnet:0.0.0.0:port,server,nowait。この場合、ファイアウォール を設定することをお勧めします。この接続は完全に認証も暗号化もされていないため、ローカルネットワークが完全に信頼できることを確認してください。

UNIX ソケット

-monitor unix:socketfile,server,nowait パラメータを指定して QEMU を実行します。その後、socatnmap、または 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 経由でモニタを公開できます。その後、openbsd-netcat または gnu-netcat のいずれかのnetcat を実行して接続します:

$ nc 127.0.0.1 port
ノート: QEMU が動作しているホスト以外のデバイスから tcp ソケットに接続できるようにするには、telnet の例で説明したように 0.0.0.0 を聞く必要があります。この場合もセキュリティに関する警告は同じです。

標準 I/O

引数 -monitor stdio で実行すると、QEMU が実行されているのと同じ端末から自動的にモニタにアクセスできます。

モニタコンソールを使って仮想マシンにキーボードの押下を送信する

設定によっては仮想マシン上で一部のキーの組み合わせがホストによって邪魔されて使えない場合があります (顕著な例として、アクティブな tty を切り替える Ctrl+Alt+F* キーの組み合わせなど) 。この問題を回避するために、問題のあるキーの組み合わせをモニタコンソール経由で代わりに送信することができます。モニタに切り替えてから sendkey コマンドを使って必要なキー入力を仮想マシンに転送します。例えば:

(qemu) sendkey ctrl-alt-f2

モニタコンソールを使ってスナップショットを作成・管理する

ノート: この機能は仮想マシンディスクイメージが qcow2 フォーマットの場合に のみ 機能します。raw イメージでは機能しません。

ときには仮想マシンの現在の状態を保存して何か問題が発生したときに仮想マシンの状態を元に戻したいということもあるでしょう。QEMU モニタコンソールにはスナップショットの作成、管理、およびマシン状態を保存されたスナップショットに戻すために必要なユーティリティが備わっています。

  • savevm name を使用するとタグ name のスナップショットが作成されます。
  • loadvm name を使用すると仮想マシンがスナップショット name の状態に戻ります。
  • delvm namename としてタグ付けされたスナップショットが削除されます。
  • info snapshots を使用すると保存済みのスナップショットのリストを表示します。スナップショットは自動増分される ID 番号とテキストタグ(スナップショット作成時にユーザが設定)の両方で識別されます。

immutable モードで仮想マシンを実行する

-snapshot パラメータを指定して QEMU を実行するだけで仮想マシンを frozen 状態で実行でき、仮想マシンの電源がオフになったときにすべての変更を破棄できます。ゲストによるディスクイメージの書き込みがあった場合、変更は /tmp 内の一時ファイルに保存され QEMU が停止したときに破棄されます。

ただし、マシンが frozen モードで実行している場合でも、後で必要に応じて、モニタコンソールを使用して次のコマンドを実行することにより、変更をディスクイメージに保存することができます。

(qemu) commit all

frozen モードで実行中にスナップショットが作成された場合、変更が明示的にディスクにコミットされない限り、QEMU の終了時に破棄されます。

モニタコンソールによる一時停止と電源オプション

モニタコマンドを使って物理マシンの操作の一部を QEMU でエミュレートできます:

  • system_powerdown は仮想マシンに ACPI シャットダウンリクエストを送信します。物理マシンの電源ボタンを押したときと同じような効果があります。
  • system_reset は物理マシンのリセットボタンと同じように仮想マシンをリセットします。仮想マシンが正常に再起動されないためデータが消失したりファイルシステムが破損する可能性があります。
  • stop は仮想マシンを停止します。
  • cont は仮想マシンを以前に停止した状態から復帰します。

仮想マシンのスクリーンショットを取得する

モニタコンソールで次のコマンドを実行することで PPM 形式で仮想マシンのグラフィックディスプレイのスクリーンショットを取得できます:

(qemu) screendump file.ppm

QEMU マシンプロトコル

QEMU マシンプロトコル (QMP) は、アプリケーションが QEMU インスタンスを制御できるようにする JSON ベースのプロトコルです。#QEMU モニタ の様に実行中のマシンと対話する方法を提供し、JSON プロトコルによりプログラム的に行うことを可能にします。すべての QMP コマンドの説明は qmp-commands に記載されています。

QMP を開始する

QMP プロトコルを使用してゲストを制御する通常の方法は、-qmp オプションを使用してマシンを起動するときに TCP ソケットを開くことです。ここでは、例えば TCP ポート 4444 を使用しています:

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

QMP エージェントと通信する方法の1つは netcatを使用することです:

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

この段階で、認識できるコマンドは qmp_capabilities のみであるため、QMP はコマンドモードに入ります。次を入力:

{"execute": "qmp_capabilities"}

これで、QMP はコマンドを受信できるようになりました。認識されたコマンドのリストを取得するには、次のコマンドを使用します:

{"execute": "query-commands"}

親イメージへの子イメージのライブマージ

block-commit コマンドを発行すると、実行中のスナップショットを親にマージできます。最も単純な形式では、次の行は子を親にコミットします:

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

このコマンドを受信すると、ハンドラはベースイメージを探し、読み取り専用モードから読み取り/書き込みモードに変換し、コミットジョブを実行します。

block-commit 操作が完了すると、イベント BLOCK_JOB_READY が発生し、同期が完了したことが通知されます。次のコマンド block-job-complete を発行すると、ジョブを正常に完了できます。

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

このようなコマンドが発行されるまで、commit 操作はアクティブなままです。 正常に完了した後、ベースイメージは読み取り/書き込みモードのままとなり、新しいアクティブレイヤになります。一方、子イメージは無効になり、クリーンアップするのはユーザの責任となります。

ヒント: デバイスとその名前のリストは、コマンド 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 を有効にする
  • -cpu host オプションで QEMU により一般的な CPU ではなくホストの正確な CPU をエミュレートさせる。
  • 特に Windows ゲストの場合、Hyper-V enlightenments を有効にする: -cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time
  • ホストマシンに複数のコアがある場合は、-smp オプションを使用してゲストにより多くのコアを割り当てる。
  • 仮想マシンに十分なメモリーが割り当てられていることを確認する。デフォルトでは、QEMU は各仮想マシンに 128 MiB のメモリーのみを割り当てます。より多くのメモリーを割り当てるには、-m オプションを使用します。たとえば、-m 1024 は 1024 MiB のメモリーを持つ仮想マシンを実行します。
  • ゲストオペレーティングシステムのドライバでサポートされている場合は、ネットワークデバイスやブロックデバイスに virtio を使用する。#virtio ドライバのインストール を参照してください。
  • ユーザーモードネットワーキングの代わりに TAP デバイスを使用する。#QEMU の Tap ネットワーク を参照してください。
  • ゲスト OS がディスクに大量の書き込みを行っている場合、ホストのファイルシステムの特定のマウントオプションの恩恵を受けられます。たとえば、barrier=0 オプションを指定して ext4 ファイルシステム をマウントできます。ファイルシステムのパフォーマンス向上オプションはデータ整合性を犠牲にする場合があるため、変更したオプションについてはドキュメントを参照してください。
  • raw ディスクイメージがある場合、キャッシュを無効にしても良いでしょう:
    $ qemu-system-x86_64 -drive file=disk_image,if=virtio,cache=none
  • natie Linux AIO を使う:
    $ qemu-system-x86_64 -drive file=disk_image,if=virtio,aio=native,cache.direct=on
  • 同じオペレーティングシステムがインストールされている複数の仮想マシンを同時に実行している場合、kernel same-page merging を有効にすることでメモリを節約できます。#KSMの有効化 を参照してください。
  • 場合によっては、ゲストオペレーティングシステムでメモリバルーニングドライバを実行し、-device virtio-balloon で QEMU を起動すると実行中の仮想マシンからメモリを回収できることがあります。
  • ICH-9 AHCI コントローラのエミュレーションレイヤを使用することができます(ただし、不安定な場合があります)。AHCI エミュレーションは Wikipedia:Native_Command_Queuing 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 サービスを使う

ブート時に QEMU VM を実行するには、次の systemd ユニットと設定を使うことができます。

/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
ノート: このサービスはコンソールポートが解放されるまで待機します。これは VM がシャットダウンされたことを意味します。

次に、変数 argshaltcmd がセットされた /etc/conf.d/qemu.d/vm_name という名前の VM 毎の設定ファイルを作成します。設定例は:

/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 - VMを安全にシャットダウンするためのコマンド。最初の例では、QEMUモニターは -monitor telnet:.. を使用して telnet 経由で公開され、VM は nc コマンドで 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_bushost_addr 、または vendor_idproduct_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_idehci または xhci であるとみなします。

次に、qemu でホストの USB に接続する方法は2つあります。

  1. デバイスを識別し、ホスト上でデバイスが接続されているバスとアドレスでデバイスに接続します。一般的な構文は次のとおりです:
    -device usb-host,bus=controller_id.0,vendorid=0xvendor_id,productid=0xproduct_id
    上の例で使用されているデバイスに適用すると、次のようになります:
    -device usb-ehci,id=ehci -device usb-host,bus=ehci.0,vendorid=0x0781,productid=0x5406
    前のオプションに...,port=port_number 設定を追加して、デバイスを接続する仮想コントローラの物理ポートを指定することもできます。これは、複数の USB デバイスを VM に追加したい場合に便利です。もう1つのオプションは 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/USB エミュレーション を参照してください。

ノート: QEMU の実行時にパーミッションエラーが起こる場合は、Udev#udev ルールを記述する のデバイスのパーミッションの設定方法を見て下さい。

SPICE による USB リダイレクト

#SPICE を使用しているのであれば、QEMU コマンドで指定しなくてもクライアントから仮想マシンに USB デバイスをリダイレクトすることが可能です。リダイレクトされたデバイスが利用できる USB スロットの数を設定することができます (スロットの数によって、同時にリダイレクトできるデバイスの最大数が決まります)。前述の -usbdevice 方式と比較して、リダイレクトに SPICE を使用する主な利点は、仮想マシンの開始後に USB デバイスをホットスワップできることで、リダイレクトから USB デバイスを削除したり新しいデバイスを追加したりするために USB デバイスを停止する必要がありません。また、ネットワーク経由でクライアントからサーバーに USB デバイスをリダイレクトすることもできます。まとめると、これは QEMU 仮想マシンで USB デバイスを使用する最も柔軟な方法です。

使用可能な USB リダイレクトスロットごとに1つの EHCI/UHCI コントローラと、スロットごとに1つの SPICE リダイレクトチャネルを追加する必要があります。 利用可能な USB リダイレクトスロットごとに1つの EHCI/UHCI コントローラを追加し、さらにスロットごとに1つの SPICE リダイレクションチャネルを追加する必要があります。たとえば、SPICE モードで仮想マシンを開始するために使用する QEMU コマンドに以下の引数を追加すると、リダイレクトに利用可能な3つの 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 を参照してください。

テンプレート:Pkg spice-gtk (Input>Select USB Devices for redirection) の spicyテンプレート:Pkg virt-viewer (File>USB device selection) の remote-viewer の両方がこの機能をサポートしています。この機能が期待どおりに動作するために必要な SPICE ゲストツールが仮想マシンにインストールされていることを確認してください (詳細については、#SPICE セクションを参照してください)。

udevによる自動 USB 転送

通常、転送されるデバイスは VM の起動時に利用可能になっている必要があります。デバイスが切断されると、転送されなくなります。

udevルール を使用して、デバイスがオンラインになったときに自動的にデバイスを接続できます。ディスク上のどこかに hostdev エントリを作成します。root に chown し、他のユーザーが変更できないようにします。

/usr/local/hostdev-mydevice.xml
<hostdev mode='subsystem' type='usb'>
  <source>
    <vendor id='0x03f0'/>
    <product id='0x4217'/>
  </source>
</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"

出典および詳細情報

警告: USB デバイスがクライアントからリダイレクトされた場合、リダイレクトが停止されるまでクライアントオペレーティングシステム自体から使用できないことに留意してください。特に、入力デバイス (マウスとキーボード) をリダイレクトしないことが重要です。仮想マシンにリダイレクトされた後、クライアントは入力デバイスに応答しなくなるため、SPICE クライアントメニューにアクセスして状況を元に戻すことは困難です。

KSM の有効化

Kernel Samepage Merging (KSM) はアプリケーションがページをマージするように登録した他のプロセスとページをマージするようにカーネルに登録できるようにする Linux カーネルの機能です。この KSM 機構によってゲストの仮想マシンは互いにページを共有することが可能になります。同じようなゲストオペレーティングシステムが多数動作する環境では、メモリの使用量を著しく節約することができます。

ノート: KSM はメモリ使用量を削減しますが、CPU 使用量を増加させる可能性があります。また、セキュリティ上の問題が発生する可能性があることにも注意してください。Wikipedia:Kernel same-page merging を参照してください。

KSM を有効にするには:

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

systemd の一時ファイルを使って KSM を永続的に有効にできます:

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

KSM が動作しているとき、マージされるページが存在するために (つまり少なくとも2つの同じような VM が動いている)、/sys/kernel/mm/ksm/pages_shared はゼロになりません。詳しくは https://docs.kernel.org/admin-guide/mm/ksm.html を参照。

ヒント: KSM のパフォーマンスを確認する簡単な方法は、そのディレクトリにあるすべてのファイルの内容を表示することです。
$ grep -r . /sys/kernel/mm/ksm/

マルチモニターのサポート

Linux QXL ドライバーはデフォルトで4台までのマルチモニター (仮想スクリーン) をサポートしています。qxl.heads=N カーネルパラメータで変更することができます。

QXL デバイスのデフォルトの VGA メモリサイズは 16M です (VRAM のサイズは 64M です)。1920x1200 のモニターを2台使用しようとすると 2 × 1920 × 4 (色深度) × 1200 = 17.6 MiB の VGA メモリが必要になるためメモリが不足します。-vga qxl-vga none -device qxl-vga,vgamem_mb=32 に置き換えることでメモリ容量を変更できます。vgamem_mb を 64M 以上に増やした場合、vram_size_mb オプションも増やす必要があります。

コピーアンドペースト

ホストとゲストの間でクリップボードを共有する方法の1つは、SPICE リモートデスクトッププロトコルを有効にし、SPICE クライアントを使用してクライアントにアクセスすることです。 #SPICE で説明されている手順に従う必要があります。この方法で実行されるゲストは、ホストとのコピーペーストをサポートします。

Windows 特有のノート

QEMU は Windows 95 から Windows 11 まで全てのバージョンの Windows を動かすことができます。

QEMU で Windows PE を実行することも可能です。

高速スタートアップ

ノート: 電源設定を変更するには管理者アカウントが必要です。

Windows 8 (またはそれ以降) のゲストでは、次の フォーラムページ で説明されているようにコントロールパネルの電源オプションから "高速スタートアップを有効にする(推奨)" を無効にすることをお勧めします. この設定は、1回おきの起動時にゲストがハングする原因となるためです。

-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 仮想マシン上で動作させることができます。QEMU 仮想マシンのためにハードウェアから Linux システムをクローンする を参照してください。

x86_64 から arm/arm64 環境への chrooting

実際の ARM ベースのデバイスではなく、ディスクイメージを直接操作する方が簡単な場合もあります。これは、root パーティションを含む SD カード/ストレージをマウントし、そこに chroot することで実現できます。

ARM chroot のもうひとつのユースケースは、x86_64 マシン上で ARM パッケージを構築することです - armutils-gitAUR が使用できます。ここで、chroot 環境を Arch Linux ARM のイメージ tarball から作成することができます - このアプローチの詳細は [2] を参照してください。

いずれにせよ、chroot から pacman を実行し、より多くのパッケージをインストールしたり、大きなライブラリをコンパイルしたりできるようになるはずです。実行可能ファイルは ARM アーキテクチャ用なので、x86 への変換は QEMU で行う必要があります。

x86_64 マシン/ホストに qemu-user-static を、qemu バイナリを binfmt サービスに登録するために qemu-user-static-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

これらの2行はそれぞれ 32ビット ARM と 64ビット ARM 用にコンパイルされた 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

最後に Chroot#chroot を使う の説明に従って SD カードのルートに chroot してください。

# chroot /mnt/sdcard /bin/bash

arch-install-scriptsarch-chroot を使用することもできます。これはネットワークサポートを得るためのより簡単な方法を提供します:

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

systemd-nspawn を使用して ARM 環境に chroot することもできます:

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

--bind-ro=/etc/resolv.conf はオプションで、chroot内部で動作中のネットワークDNSを提供します。

マウス入力をつかまない

この記事あるいはセクションで使われている用語や表現には問題が存在します。
議論: オプションが実際に何をするのか説明されていません。それが副作用を引き起こしているのか、回避しているのか? (議論: トーク:QEMU#)

タブレットモードには、QEMU ウィンドウでマウス入力をつかまないという副作用があります:

-usb -device usb-tablet

いくつかの -vga バックエンドで動作しますが、そのうちのひとつは virtio です。

トラブルシューティング

この記事あるいはセクションは QEMU/トラブルシューティング と合併することが議論されています。
ノート: このセクションは専用のサブページに分割できる長さです。 (議論: トーク:QEMU#)

マウスカーソルが敏感すぎたり迷走する

カーソルが画面を飛び回って手に負えない場合、QEMU を起動する前にターミナルに次を入力することで直るかもしれません:

$ export SDL_VIDEO_X11_DGAMOUSE=0

このコマンドで直ったら、~/.bashrc ファイルにコマンドを追加することができます。

カーソルが表示されない

マウスカーソルを表示するには -display default,show-cursor=on を QEMU のオプションに追加してください。

オプションを追加しても表示されない場合、ディスプレイデバイスが正しく設定されているか確認してください。例: -vga qxl

#Mouseの統合 で説明されているように -usb-device usb-tablet を試すこともできます。これはデフォルトの PS/2 マウスエミュレーションを上書きし、追加のボーナスとしてホストとゲスト間でポインタ位置を同期させます。

2つの異なるマウスカーソルが表示される

ヒント #マウスの統合 を適用してください。

VNC使用時のキーボードの問題

VNC の使用中、ここに (生々しく詳細に) 書かれているキーボードの問題を経験するかもしれません。解決策は QEMU で -k オプションを使用 しない ことと、gtk-vncgvncviewer を使用することです。libvirt のメーリングリストに投稿された この メッセージも参照してください。

キーボードが壊れているまたは矢印キーが動作しない

キーの一部が動かなかったり間違ったキーが "押されてしまう" (特に矢印キー) ときは、おそらくキーボードレイアウトをオプションとして指定する必要があります。キーボードレイアウトは /usr/share/qemu/keymaps で探すことができます。

$ qemu-system-x86_64 -k keymap disk_image

キーマップファイルを読み込めない

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

-k 引数に渡された無効な keymap が原因です。たとえば、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

他の ハイパーバイザ が動作しています。同時に複数のハイパーバイザを動かすのは推奨されていません、もしくは不可能です。

libgfapi エラーメッセージ

起動時に以下のエラーメッセージが表示される場合:

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

glusterfsインストール するか無視してください。GlusterFS はオプションの依存関係です。

ライブ環境でカーネルパニックが発生する

稼働中の環境を起動した場合(あるいは、システムを起動した場合)、次のようなことが起こります。 ライブ環境を起動した(あるいはシステムを起動)際に以下が発生する:

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

または起動を妨げる他の処理(例えば initramfs をアンパックできない、サービス foo を起動できない)など。 -m VALUE スイッチを付けて適当な量の RAM を指定して VM を開始してみてください。メモリスイッチがない場合、RAM が足りなくなると上記のような問題が発生することがあります。

Windows 7 ゲストの音質が酷い

Windows 7 ゲストで hda オーディオドライバを使用すると、音質が低下する場合があります。-soundhw AC97 引数をQEMU に渡してオーディオドライバを 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 ゲストは起動時に "System Thread Exception Not Handled" という一般的な互換性例外を発生させることがあります。これは実機で奇妙な振る舞いをするレガシードライバ原因であることが多いようです。KVM マシンでは一般的に CPU モデルをcore2duo に設定することでこの問題を解決できます。

特定の Windows のゲームやアプリケーションでクラッシュやブルスクリーンが発生する

物理マシンでは問題なく動作するのに、VM で実行すると予期せずにクラッシュすることがあります。root で dmesg-wH を実行したときに MSR というエラーが発生した場合、クラッシュの原因はゲストがサポートされていない Model-specific registers (MSRs) にアクセスしようとすると、KVM が一般保護違反 (GPF) を起こすためです。これにより、ゲストアプリケーション/OSがクラッシュすることがよくあります。これらの問題の多くは、KVM モジュールに ignore_msrs=1 オプションを指定して実装されていない MSR を無視することで解決できます。

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

上記のオプションが役に立つのは以下のような場合です:

  • GeForce Experience でサポートされていない CPU が存在するとエラーが表示される。
  • StarCraft 2 や L.A.Noire で KMODE_EXCEPTION_NOT_HANDLED が発生して Windows 10 が確実にブルースクリーンになる。これらの場合、ブルースクリーン情報はドライバファイルを識別しません。
警告: これは通常は安全であり、一部のアプリケーションはこれ無しには動作しない可能性がありますが、未知のMSRアクセスを黙って無視すると、VM や他の VM の中の他のソフトウェアが動作しなくなる可能性があります。

VM 内のアプリケーションで長い遅延が発生したり開始に長い時間がかかる

これは、VM で使用可能なエントロピーが不足していることが原因である可能性があります。VirtIO RNGデバイス を VM に追加するか、Haveged などのエントロピー生成デーモンをインストールすることによって、ゲストがホストのエントロピープールにアクセスできるようにすることを検討してください。

逸話として、OpenSSHは 不十分なエントロピーの下で接続を受け入れ始めるのに時間がかかりますが、その理由はログには示されません。

高い割り込みレイテンシとマイクロスタッタリング

この問題は小さな一時停止(カクつき)として現れ、特にゲームなどのグラフィックスを多用するアプリケーションで顕著になります。

QXL ビデオの低解像度化

QEMU 4.1.0 では、QXL ビデオがスパイスで表示されると低解像度に戻るというリグレッションが発生しました。[3] たとえば、KMS が開始すると、テキストの解像度が 4x10 文字に低下することがあります。GUI の解像度を上げようとすると、サポートされている最低の解像度になることがあります。

回避策として、次の形式でデバイスを作成してください:

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

セキュアブート対応 OVMF を使用すると VM が起動しない

edk2-ovmf/usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.fdSMM サポート付きでビルドされています。VM で S3 サポートが無効になっていない場合、VM がまったく起動しない可能性があります。

qemu コマンドに -global ICH9-LPC.disable_s3=1 オプションを追加してください。

QEMU でセキュアブートを使用するために必要なオプションの詳細は FS#59465および https://github.com/tianocore/edk2/blob/master/OvmfPkg/README を参照してください。

VM が Arch ISO で起動しない

Arch ISO イメージから初めて VM を起動しようとすると、ブートプロセスがハングします。ブートメニューで e を押して console=ttyS0 をカーネルブートオプションに追加すると、さらに多くのブートメッセージと次のエラーが表示されます:

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

このエラーメッセージは、実際の問題が何なのかを明確に示すものではありません。問題は、QEMU が VM に割り当てるデフォルトの 128MB の RAM にあります。-m 1024 で制限を 1024MB に増やすと問題が解決し、システムが起動します。その後、通常どおり Arch Linux のインストールを続けることができます。インストールが完了したら、VM へのメモリ割り当てを減らすことができます。1024MB が必要になるのは、RAM ディスクの要件とインストールメディアのサイズによるものです。 arch-releng メーリングリストのこのメッセージこのフォーラムのスレッド を参照してください。

ゲスト CPU の割り込みが発生しない

OSDev wiki に従って独自のオペレーティングシステムを作成している場合や、QEMU の gdb インターフェースで -s フラグを使用してゲストアーキテクチャアセンブリコードをステップ実行している場合、QEMU を含む多くのエミュレーターが、通常はいくつかの CPU 割り込みを実装し、多くのハードウェア割り込みは実装していないということを知っておくと役に立ちます。あなたのコードが割り込みを発生させているかどうかを知る1つの方法は、以下を使用して:

-d int

標準出力に割り込み/例外の表示を有効にすることです。

QEMU が提供するその他のゲストデバッグ機能については、以下を参照してください:

qemu-system-x86_64 -d help

もしくは、x86_64 をあなたの選択したゲストアーキテクチャに置き換えてください。

参照

翻訳ステータス: このページは en:QEMU の翻訳バージョンです。最後の翻訳日は 2022-10-15 です。もし英語版に 変更 があれば、翻訳の同期を手伝うことができます。