Linux システム コール のマニュアル ページをsendfile
読んで、呼び出し元のプログラムがいつin_fd
EOFにあるかを知ることができるかどうか疑問に思っています。おそらく、これは戻り値 0 によって通知される可能性がありますが、これは戻り値 0 が実際に何を意味するのかという問題につながります。sendfile
のような場合write
、戻り値 0 は 0 バイトがコピーされたことを意味します。しかし、sendfile
が のような場合read
、戻り値 0 は EOF を意味します。を使用するためにからin_fd
にコピーするバイト数を事前に知っておく必要がありますか? 0 を返すとはどういう意味ですか?out_fd
sendfile
sendfile
4 に答える
それを知る直接的な方法はないと思いますが、実際には問題ではありません。通常、入力ファイルのサイズを見つけて、stat/fstat
それを使用して転送をカウントします。ソケットの端はあなたにとって重要ではありません。
これが問題になる唯一の状況は、拡大または縮小しているファイルを転送する場合です。入力ファイルを mmap 化する必要があり、そのような状況で mmap を使用すると (巧妙なコードがなくても) 起こりうる悪いことを考えると、おそらく sendfile を使用しないでください。
読み取りカウントにオフセットパラメータを使用できます。
Manページによると
offsetがNULLでない場合は、sendfile()がin_fdからのデータの読み取りを開始するファイルオフセットを保持する変数を指します。sendfile()が戻ると、この変数は、読み取られた最後のバイトに続くバイトのオフセットに設定されます。オフセットがNULLでない場合、sendfile()はin_fdの現在のファイルオフセットを変更しません。それ以外の場合、現在のファイルオフセットは、in_fdから読み取られたバイト数を反映するように調整されます。
countは、ファイル記述子間でコピーするバイト数です。
戻り値転送が成功した場合、out_fdに書き込まれたバイト数が返されます。エラーの場合、-1が返され、errnoが適切に設定されます。
はい、それは戻り値0が書き込みソケットにコピーされたデータがないことを意味します。
送信されたバイト数が 0 の場合、EOF に達したと見なすことができます。
sent = sendfile(out_fd, in_fd, &offset, nbytes);
if (sent == 0) {
// EOF
...
}
この仮定は、ノンブロッキング ソケットの場合にも当てはまります。
私の場合、ファイルがrsyncによって切り捨てられることに遭遇し、アプリはsendfileを使用して同時にファイルを送信します。この状態でアプリが CPU を 100% 消費していることがわかりました。次の記事を参照してコードを修正すると、質問が消えます。 http://www.linuxjournal.com/article/6345
ポイントは、F_SETLEASE を使用してアプリのファイル リースを取得することです。