ゼロコピーのメカニズムを説明する記事を読んだばかりです。
Scatter/Gatherサポートがある場合とない場合のゼロコピーの違いについて説明します。
SGをサポートしないNIC、データコピーは次のとおりです
SGをサポートするNIC、データコピーは次のとおりです
つまり、SGをサポートするゼロコピーは1つのCPUコピーを排除できます。
私の質問は、なぜカーネルバッファ内のデータが分散する可能性があるのかということです。
ゼロコピーのメカニズムを説明する記事を読んだばかりです。
Scatter/Gatherサポートがある場合とない場合のゼロコピーの違いについて説明します。
SGをサポートしないNIC、データコピーは次のとおりです
SGをサポートするNIC、データコピーは次のとおりです
つまり、SGをサポートするゼロコピーは1つのCPUコピーを排除できます。
私の質問は、なぜカーネルバッファ内のデータが分散する可能性があるのかということです。
Linuxカーネルのマッピング/メモリ割り当て機能は、デフォルトで仮想的に隣接しているが、物理的に分離している可能性のあるメモリ領域を作成するためです。
つまり、sendfile()
内部で行われるファイルシステムからの読み取りは、カーネル仮想メモリのバッファに送られます。これは、DMAコードがネットワークカードのDMAエンジンが実行できるものに(より適切な単語がないために)「変換」する必要があります。
DMAは(常にではありませんが)物理アドレスを使用するため、データバッファを複製するか(メモリの特別に割り当てられた物理的に隣接する領域、上記のソケットバッファに)、または1つの物理ページで転送することを意味します。 -a-time。
一方、DMAエンジンが、物理的に分離した複数のメモリ領域を1つのデータ転送(「スキャッターギャザー」と呼ばれる)に集約できる場合は、バッファーをコピーする代わりに、物理アドレスのリストを渡すだけで済みます。 (カーネルバッファの物理的に隣接するサブセグメントを指します。これは上記の集約記述子です)。物理ページごとに個別のDMA転送を開始する必要がなくなります。これは通常は高速ですが、実行できるかどうかはDMAエンジンの機能によって異なります。
Re:私の質問は、なぜカーネルバッファ内のデータが分散する可能性があるのかということです。
すでに散らばっているので。TCPソケットの前のデータキューは、ネットワークインターフェイスに送信されるデータグラムに分割されていません。Scatterを使用すると、データを現在の場所に保持し、ハードウェアで受け入れ可能なフラットバッファーを作成するためにデータをコピーする必要がなくなります。
収集機能を使用すると、ネットワークカードにデータグラムを提供できます。このデータグラムは、メモリ内のさまざまなアドレスで分割され、元のソケットバッファへの参照になります。カードはそれらの場所からそれを読み取り、単一のユニットとして送信します。
収集なし(ハードウェアには単純な線形バッファーが必要)、データグラムは連続して割り当てられたバイト文字列として準備する必要があり、それに属するすべてのデータはmemcpy
、ソケットでの送信のためにキューに入れられたバッファーから所定の位置に配置する必要があります。
ソケットに書き込む場合、パケットのヘッダーはユーザーデータとは異なる場所でアセンブルされるため、ネットワークパケットに統合するには、少なくともヘッダーとデータを取得するために、デバイスに「収集」機能が必要です。 。
また、CPUがデータを読み取らなくて済むように(したがって、キャッシュが二度と必要になることのない無駄なものでいっぱいになる)、ネットワークカードは独自のIPおよびTCPチェックサムを生成する必要があります(ここではTCPを想定しています。バルクデータ転送の99%がTCPになるためです)。今日ではすべてができるので、これは問題ありません。
よくわからないのは、これがすべてTCP_CORKとどのように相互作用するかです。
ほとんどのプロトコルには独自のヘッダーがある傾向があるため、架空のプロトコルは次のようになります。
クライアント:リクエストの送信サーバー:メタデータを送信します。ファイルデータを送信する
そのため、サーバーアプリケーションがメモリ内のいくつかのヘッダーを組み立て、write()を発行し、その後にsendfile()のような操作を行う傾向があります。この場合でも、ヘッダーはカーネルバッファにコピーされると思います。