virtioとvhostの違い
virtio
Section titled “virtio”ゲストOSが準仮想化デバイスにアクセスするときのインターフェイスを定めたAPI仕様。
virtio インターフェイスを実装したデバイスはいくつかある。
- virtio-net
- virtio-blk
- virtio-scsi
- virtiofs
Linuxカーネルでは vqueue と vring を使ってデータを管理する。この実現にはQEMU, KVM, libvirtが関係している。
仮想化を支援するカーネルの機能。メモリ管理やリソース管理の機構が実装されている。
KVMと一緒に利用する場合はデバイスのエミュレーション部分を担当する。ゲストOSを立ち上げるごとにQEMUプロセスが生成される。
libvirt
Section titled “libvirt”これはXMLで記述した設定ファイルをQEMUのコマンドラインオプションに展開するためのツールで、プログラミング言語のライブラリではなかった。なので利用しなくても動作に支障はない。
vhost は virtio の一部を実装したプロトコル。デバイスごとにフロントエンドとバックエンドが定義される。
全てをQEMUプロセスで実装すると、データの入出力があるたびにコンテキストスイッチやユーザー/カーネル空間の切り替えが発生して非常に効率が悪い。なので効率的な実装にオフロードするためのプロトコルとして定義される。
例えばネットワークの場合、vhost を使う場合でも使わない場合でもゲストOSからみたフロントエンドは virtio-net から変わらず、ゲストOSのカーネル空間でコントロールプレーンの処理(フロントエンド)を担当する。しかし vhost を使わないときは virtio-net がゲストからみたバックエンドとなるが、これはQEMUに実装されているのでバックエンドがパケットを処理する際に vmexit 等でオーバーヘッドが発生して都合が悪い。そのため、vhost-net バックエンドではホストOSのカーネル空間でデータプレーンの処理(バックエンド)を担当する。結局フロントエンドが動作する場所はQEMUプロセスなので、ホストOSからみるとユーザー空間なのだが、VMEXIT 等でコンテキストスイッチが起きないような実装になっているらしい。これはRed Hatの図が分かりやすい。
vhost-net の他には以下のようなバックエンドがある。
| バックエンド | 実装 | 説明 |
|---|---|---|
| vhost-net | カーネル空間 | ネットワークのデータ転送を行う |
| vhost-user-net1 | ユーザー空間 | ネットワークのデータ転送を行う |
| vhost-blk | カーネル空間 | ブロックデバイスのIO処理を行う |
| vhost-user-blk | ユーザー空間 | ブロックデバイスのIO処理を行う |
| vhost-mouse-pci | カーネル空間 | |
| vhost-user-input | ユーザー空間 |
コンテキストスイッチの有無でいえばユーザー空間で実装する意味があるのかと思うが、DPDKやSPDKでは全てをユーザー空間で処理するので、そういう用途なのだろう。
vhost-userプロトコル
Section titled “vhost-userプロトコル”ユーザープロセスに処理をオフロードするための、QEMUとユーザープロセス間で扱うプロトコル。vhost のフロントエンドはQEMUが担当し、バックエンドは別のユーザープロセスが対応する。
以下のドキュメントでバックエンドのリストが掲載されている。
Footnotes
Section titled “Footnotes”-
歴史的な理由なのか分からないが古いドキュメントではvhost-userと表記されている場合もある ↩