27

splice が導入されたとき、sendfile が splice に基づいて再実装されたことがカーネル リストで議論されました。スプライス SLICE_F_MOVE のドキュメントには次のように記載されています。

コピーする代わりにページを移動してみてください。これはカーネルへのヒントにすぎません。カーネルがページをパイプから移動できない場合、またはパイプ バッファがフル ページを参照していない場合でも、ページはコピーされる可能性があります。このフラグの最初の実装にはバグがありました。そのため、Linux 2.6.21 以降では何もしません (ただし、splice() 呼び出しでは引き続き許可されます)。将来的には、正しい実装が復元される可能性があります。

ということは、Linux にはソケットに書き込むためのゼロコピー方式がないということでしょうか? それとも、これはある時点で修正され、何年もの間誰もドキュメントを更新していませんでしたか? 最新の 3.x カーネル バージョンのいずれかで、sendfile または splice のいずれかにゼロ コピー実装がありますか?

Google はこのクエリに対する回答を持っていないので、vmsplice と splice または sendfile を単純な古い書き込みよりも使用する利点があるかどうかを知りたがっている次の貧弱なシュマックのために、stackoverflow の質問を作成しています。

4

2 に答える 2

19

sendfileそれ以来ずっと、今でもゼロコピーです (ハードウェアで許可されていると仮定しますが、通常はそうです)。ゼロコピーであることは、そもそもこのシステムコールを持つことの全体的なポイントでした。sendfileは現在、 のラッパーとして実装されていますsplice

spliceこれは、 もゼロコピーであることを示唆しており、実際にそうです。少なくとも理論的には、そして少なくとも場合によっては。問題は、それを正しく使用して確実に機能させ、ゼロコピーにする方法を見つけることです。ドキュメントは...控えめに言ってもまばらです。

特に、spliceページが「贈り物」として与えられた場合、つまり、ページをもう所有していない場合にのみ、ゼロコピーのみが機能します (正式には、実際にはまだ所有しています)。ファイル記述子をソケットに接続するだけであれば問題ありませんが、アプリケーションのアドレス空間から、またはあるパイプから別のパイプにデータを接続する場合は大きな問題になります。その後(そしていつ)ページをどうするかは不明です。ドキュメントには、後でページに触れたり、ページで何かをしたりしてはいけないと記載されています。したがって、ドキュメントの文字に従えば、メモリをリークする必要があります。
それは明らかに正しくありません (それはあり得ません) が、(少なくともあなたにとっては!) そのメモリをいつ再利用または解放しても安全かを知る良い方法はありません。カーネルはsendfileTCP ACK を受信するとすぐに、データが二度と必要ないことがわかるからです。問題は、ACK が表示されないことです。spliceが返されたときにわかるのは、データの送信が受け入れられたということだけです (ただし、データが既に送信されているのか受信されているのか、いつ発生するのかはわかりません)。つまり、手動で ACK を実行するか (信頼できる UDP で無料で提供されます)、または相手側が要求に対する応答を送信した場合、明らかに要求を受け取ったに違いないと仮定することによって、アプリケーション層で何らかの
方法で これを把握する必要があります。 .

管理しなければならないもう 1 つのことは、有限のパイプ スペースです。デフォルトは非常に小さいですが、サイズを大きくしても、任意のサイズのファイルを単純にスプライスすることはできません。sendfile一方、それを行うだけで済みます。これはクールです。

全体として、うまく機能し、うまく機能し、上記の詳細を気にする必要がないsendfileため、素晴らしいです。それは万能薬ではありませんが、確かに素晴らしい追加です. 個人的には、全体が大幅に見直され、何を (いつ) しなければならないか、何をする必要がないかが 100% 明確になるまで、およびその家族 から離れていたいと思います。
splice

いずれにせよ、ほとんどのアプリケーションでは、単純な古いものに対する実際の効果的な利点writeはわずかです。数年前の Torvalds 氏の丁寧ではないコメントを思い出します (BSD には、writeゼロコピーを取得するためにページを再マッピングする魔法のような形式がありましたが、Linux にはありませんでした)。問題はありませんが、ページでいたずらをするのは[ここでは繰り返さない]です。

于 2014-08-12T13:33:03.670 に答える