sendfile
それ以来ずっと、今でもゼロコピーです (ハードウェアで許可されていると仮定しますが、通常はそうです)。ゼロコピーであることは、そもそもこのシステムコールを持つことの全体的なポイントでした。sendfile
は現在、 のラッパーとして実装されていますsplice
。
splice
これは、 もゼロコピーであることを示唆しており、実際にそうです。少なくとも理論的には、そして少なくとも場合によっては。問題は、それを正しく使用して確実に機能させ、ゼロコピーにする方法を見つけることです。ドキュメントは...控えめに言ってもまばらです。
特に、splice
ページが「贈り物」として与えられた場合、つまり、ページをもう所有していない場合にのみ、ゼロコピーのみが機能します (正式には、実際にはまだ所有しています)。ファイル記述子をソケットに接続するだけであれば問題ありませんが、アプリケーションのアドレス空間から、またはあるパイプから別のパイプにデータを接続する場合は大きな問題になります。その後(そしていつ)ページをどうするかは不明です。ドキュメントには、後でページに触れたり、ページで何かをしたりしてはいけないと記載されています。したがって、ドキュメントの文字に従えば、メモリをリークする必要があります。
それは明らかに正しくありません (それはあり得ません) が、(少なくともあなたにとっては!) そのメモリをいつ再利用または解放しても安全かを知る良い方法はありません。カーネルはsendfile
TCP ACK を受信するとすぐに、データが二度と必要ないことがわかるからです。問題は、ACK が表示されないことです。splice
が返されたときにわかるのは、データの送信が受け入れられたということだけです (ただし、データが既に送信されているのか受信されているのか、いつ発生するのかはわかりません)。つまり、手動で ACK を実行するか (信頼できる UDP で無料で提供されます)、または相手側が要求に対する応答を送信した場合、明らかに要求を受け取ったに違いないと仮定することによって、アプリケーション層で何らかの
方法で
これを把握する必要があります。 .
管理しなければならないもう 1 つのことは、有限のパイプ スペースです。デフォルトは非常に小さいですが、サイズを大きくしても、任意のサイズのファイルを単純にスプライスすることはできません。sendfile
一方、それを行うだけで済みます。これはクールです。
全体として、うまく機能し、うまく機能し、上記の詳細を気にする必要がないsendfile
ため、素晴らしいです。それは万能薬ではありませんが、確かに素晴らしい追加です. 個人的には、全体が大幅に見直され、何を (いつ) しなければならないか、何をする必要がないかが 100% 明確になるまで、およびその家族
から離れていたいと思います。
splice
いずれにせよ、ほとんどのアプリケーションでは、単純な古いものに対する実際の効果的な利点write
はわずかです。数年前の Torvalds 氏の丁寧ではないコメントを思い出します (BSD には、write
ゼロコピーを取得するためにページを再マッピングする魔法のような形式がありましたが、Linux にはありませんでした)。問題はありませんが、ページでいたずらをするのは[ここでは繰り返さない]です。