Linux 仮想化 KVM-Qemu Virtqueue の分析

Linux 仮想化 KVM-Qemu Virtqueue の分析

[[390061]]

この記事はWeChatの公開アカウント「LoyenWang」から転載したもので、著者はLoyenWangです。この記事を転載する場合は、LoyenWang公式アカウントまでご連絡ください。

背景

  • ソースコードを読んでみろよ! --魯迅著
  • 一枚の写真は千の言葉に値する。 --ゴーリキー著

例:

  1. KVM バージョン: 5.9.1
  2. QEMU バージョン: 5.0.0
  3. ツール: Source Insight 3.5、Visio
  4. この記事はブログガーデンで同期されています: https://www.cnblogs.com/LoyenWang/

1. 概要

ワンワンワン、最近忙しくて更新のリズムが乱れていました。取り急ぎお詫び申し上げます。

  • 前回のシリーズでは、Virtio デバイスと Virtio ドライバーについてすでに説明しました。この記事では、virtqueue を分析します。
  • Virtqueue は、フロントエンドとバックエンド間のデータ交換に使用されます。このデータ キューを見ると、まず思い浮かぶのはリング バッファです。実際の実装はどのようになりますか?

2. データ構造

まずコアデータ構造を見てみましょう。

  • 通常、Virtio デバイスが Virtqueue を操作する場合、外部インターフェースとして理解できる struct virtqueue 構造体を使用し、Virtqueue メカニズムの実装は struct vring_virtqueue 構造体に依存します。
  • Virtqueue には、struct vring によって編成された 3 つのコア データ構造があります。
  1. struct vring_desc: 記述子テーブル。各記述子はメモリの一部を指します。メモリタイプは、それぞれ出力と入力を表す out タイプと in タイプに分けられます。ドライバーはメモリ管理を担当します。この構造体の次のフィールドは、複数の記述子を含む記述子チェーンを形成するために使用でき、フラグ フィールドは、読み取り専用や書き込み専用などのプロパティを記述するために使用されます。
  2. struct vring_avail: 使用可能な記述子領域。デバイスで使用可能な記述子 ID を記録するために使用されます。その本体は配列リングであり、これは実際にはリング バッファーです。
  3. struct vring_used: 使用された記述子領域。デバイスが処理した記述子 ID を記録するために使用されます。同様に、そのリング配列もリング バッファです。 struct vring_avail とは異なり、デバイスによって書き戻されたデータの長さも記録します。

もちろん、これは少し直感的ではないので、ここに図を示します。

  • 簡単に言えば、ドライバーはメモリ (scatterlist) を割り当て、それを virtqueue_add を通じて記述子テーブルに追加し、記述子テーブル内のエントリが特定の物理アドレスに対応できるようにします。実際、それはリソースプールとして理解することができます。
  • ドライバーは、使用可能なリソースを struct vring_avail に更新できます。つまり、使用可能な記述子 ID をリング配列に追加します。リング バッファに精通している学生は、そのメカニズムを明確に理解しているはずです。これは、ヘッドとテールの 2 つのポインタを維持することによって管理されます。ドライバーはヘッド ポインター (idx) の更新を担当し、デバイスはテール ポインターの更新を担当します (Qemu のデバイスは last_avail_idx を維持する責任があります)。ヘッドポインターとテールポインターは常にお互いを追いかけています。
  • デバイスが終了すると、使用された記述子 ID が struct vring_used に更新されます。 vring_virtqueue 自体は last_used_idx を維持し、そのメカニズムは struct vring_avail と一致しています。

3. プロセス分析

3.1 送信

ドライバーがデバイスにデータを送信する必要がある場合、プロセスは上記のようになります。

①A はバッファを割り当てて Virtqueue に追加することを意味し、①B は Used キューからバッファを取得することを意味します。2 つの方法のいずれかを選択します。

②送信のためにデータをバッファにコピーすることを示します。

③Availキュー内の記述子インデックス値を更新することを示します。デバイスが正しい値を確認できるようにするために、ドライバーはメモリ バリア操作を実行する必要があることに注意してください。

④と⑤は、ドライバーがデバイスにデータを取得するよう通知することを示します。

⑥デバイスがAvailキューから記述子インデックス値を取得することを示します。

⑦は記述子インデックスに対応するアドレスのデータを取り出すことを意味する。

⑧デバイスが使用済みキュー内の記述子インデックスを更新したことを示します。

⑨および⑩は、デバイスがデータが取得されたことをドライバーに通知することを示します。

3.2 受信

ドライバーがデバイスからデータを受信すると、プロセスは上記のようになります。

① デバイスがAvailキューから利用可能な記述子インデックス値を取得することを示します。

②記述子インデックスに対応するアドレスにデータをコピーすることを示します。

③使用済みキュー内の記述子インデックス値を更新することを示します。

④と⑤は、デバイスがドライバーにデータを取得するよう通知することを示します。

⑥ドライバーが使用済みキューから使用済み記述子インデックス値を取得することを示します。

⑦は記述子インデックスに対応するアドレスのデータを取り出すことを意味する。

⑧Availキュー内の記述子インデックス値が更新されたことを示します。

⑨と⑩は、ドライバーがデバイスに新しい記述子が利用可能であることを通知することを示します。

3.3 コード分析

コード分​​析は、次の図 (Virtio-Net) を中心に行われます。面倒なので、一方向のデータ転送のみを分析します。

3.3.1 仮想キューの作成

  • 前回のシリーズの記事では、virtio デバイスとドライバーを分析しました。 Virtio-Net は PCI ネットワーク カード デバイス ドライバーであり、それぞれ virtnet-probe と virtio_pci_probe ですべての初期化を完了します。
  • virtnet_probe 関数のエントリでは、Virtqueue は init_vqs を通じて初期化されます。呼び出し関係は図に示されています。最後に、vring_create_virtqueue が呼び出され、Virtqueue が作成されます。
  • この作成プロセス中、Virtqueue の作成に必要な情報を取得するために PCI を介してデバイス構成スペースを読み取るなど、一部の詳細は無視されます。
  • 最後に、vring_virtqueue データ構造の初期化が実行されます。 vring データ構造のメモリ割り当てもドライバー内で完了し、構造全体はドライバーによって管理および保守されます。

3.3.2 virtio-netドライバは

  • ネットワーク データの送信は、start_xmit 関数を通じてドライバーに実装されます。
  • xmit_skb 関数では、sg_init_table が sg リストを初期化し、sg_set_buf が sg を特定のバッファーにポイントし、skb_to_sgvec がソケット バッファー内のデータで sg を埋めます。
  • virtqueue_add_outbuf を介して sg を Virtqueue に追加し、Avail キュー内の記述子のインデックス値を更新します。
  • virtqueue_notify は、デバイスがデータを取得できることを通知します。

3.3.3 Qemu virtio-netデバイス受信

  • ゲスト ドライバーがレジスタに書き込むと、KVM に転送され、Qemu が最終的にそれをキャプチャして処理します。エントリ関数は kvm_handle_io です。
  • Qemu は、IO メモリ領域の読み取りおよび書き込み操作関数を設定します。ゲストが IO 操作を実行すると、最終的に操作関数がトリガーされます。 Virtio-Net の場合は PCI デバイスなので、操作関数は virtio_pci_config_write になります。
  • virtio_pci_config_write 関数では、ゲストの書き込み操作を判断して処理します。たとえば、VIRTIO_PCI_QUEUE_NOTIFY が発生すると、ゲスト ドライバーの通知を処理するために virtio_queue_notify が呼び出され、最後に handle_output 関数がコールバックされます。
  • Virtio-Net デバイスの場合、送信されるコールバック関数は virtio_net_handle_tx_bh であり、操作は virtio_net_flush_tx で完了します。
  • 一般的な操作モデル: virtqueue_pop を介して Avail キューからアドレスを取得し、データを処理し、virtqueue_push を介して処理された記述子インデックスを使用済みキューに更新し、virtio_notify を介してゲスト ドライバーに通知します。
  • Virtqueue のデザインコンセプトは非常に巧妙です。これは virtio だけでなく、AMP システム内のプロセッサ間の通信にも使用されます。

とりあえずこれで終わりです。また次回お会いしましょう。

参照する

https://www.redhat.com/en/blog/virtqueues-and-virtio-ring-how-data-travels

仮想 I/O デバイス バージョン 1.1

<<:  4 Windows 仮想デスクトップ管理の制限

>>:  「MQ シリーズをマスターする」 - カフカの謎を解き明かす

推薦する

旅行サイト運営における珠海連盟と同城連盟のホテル協力の比較

こんにちは、旅行ウェブマスターの皆さん。私は普通の旅行ウェブマスターです。私のウェブサイトは「旅遊人...

組織がビジネスをクラウドに移行する6つの理由

今日、ますます多くの組織がビジネスをクラウドに移行しています。データ センターのライフサイクルの終わ...

Weibo を使って自分のウェブサイトを宣伝する方法

最近、ウェブサイトを運営している人たちはWeiboマーケティングをやったことがないので、会ったときに...

AR Cloud はインターネットビジネスの状況を一変させることができるでしょうか?

[[249931]]ケビン・ケリー氏は、Wired誌の創刊編集者であり、有名なベストセラー作家、テク...

中小企業のウェブサイトのSEO最適化を行う際に注意すべきこと

SEO テクニックを習得し、SEO の考え方を柔軟に適用すると、SEO 最適化を自然にビジネスに取り...

ウェブサイトのトラフィック統計分析についてもう一度お話しします

人生日記には、喜び、悲しみ、怒り、幸せ、そして成長体験を記録できます。では、ウェブサイトのトラフィッ...

DedecmsウェブサイトのホームページSEO最適化、99%の人がまだこの愚かな方法を使用しています

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスウェブサイトのホームペー...

ウェブサイトコンテンツ診断の最適化に関する基礎知識

SEOウェブサイト分析といえば、すべてのSEOウェブマスターがウェブサイト診断を思い浮かべると思いま...

ブランドかプラットフォームか:中小規模のインターネット起業家はどこへ向かうのか?

序文:紆余曲折を経ての思い昨年の3月から、私はいくつかの小さなウェブサイトを運営しています。いくつか...

ウェブサイトを運営する際に、どのように顧客を引き付けますか?

21世紀、インターネットは人々の生活に欠かせない要素になりました。あなたも例外ではありませんよね?こ...

簡単な説明:検索エンジンで上位ランクを獲得するための3つのポイント

検索エンジンのランキングを行うと、ホームページの上位 3 ページに最も多くのトラフィックがあることが...

#黒5+CM# itldc: 13ユーロ/年、1GメモリKVM、無制限トラフィック。専用サーバープロモーションもあります

itldc は古いブランドです。ブラックフライデーとサイバーマンデーのプロモーションはかなり前にリリ...

#ウェブマスターのおすすめ# knownhost: 完全に管理された VPS、30% 割引コード、ウェブサイト構築に最も安心な VPS

有名で定評のあるフルマネージドホスティング プロバイダー knownhost は、次の夏のプロモーシ...

クラウドが後退し、エッジコンピューティングが台頭し、エッジコンピューティングは爆発的な応用の時代を迎える

5Gの商用化が近づくにつれ、あらゆるものがインターネットになる時代が加速し、ネットワークインフラも「...

Kubernetes誕生から7年、利点と課題が共存

2021 年 6 月 7 日、Kubernetes は 7 周年を迎えます。 Kubernetes ...