2017-12-29 22 views
1

1つのスレッドがファイルに書き込み(またはそれを削除する)、重複する位置に対して同時にそのファイルのsendfile()を呼び出します。sendfile()が進行中にファイルが書き換えられた場合の動作は何ですか

ここで期待される動作は何ですか?

また、私の理解が正しい場合、sendfile呼び出しはソケット(ファイルの説明、位置、長さ)にレコードを追加し、呼び出し元に戻ります。 (まだソケットのバッファへのコピーはしていませんか?)、sendfile()はファイルを変更する前に戻ります。OSはファイルが完全に送信されるまでファイルの存在に依存します。

ファイルが送信されるまでの変更結果はどうなりますか?

+1

オープンファイルを削除しても、カーネルのファイルハンドル(およびプロセスの 'fd')は、ファイルが閉じられるまでファイルを「生きている」状態に保ちます。これはまた、 'fd'ハンドルに影響を与えずに開いているファイルを"移動 "できる理由です。編集によって引き起こされる競争条件については...まあ、それはレースです。 sendfileが編集後に動作する場合、編集されたバージョンで動作します。 – Myst

+0

書き込みは、実行中のプログラム、OS、さらにはHDコントローラによってバッファされることがあります。おそらく3つの連続した全てであろう。ベスト・プラクティスは、マルチスレッド・プログラムで同じファイルを読み書きするときにアトミック・ガードを追加することです。 – usr2564301

+1

@ usr2564301 HDコントローラはアプリケーションとは無関係です。 Linuxには統一バッファキャッシュがあり、すべてのプロセスが同じカーネルファイルバッファを使用します。 – Barmar

答えて

3

予想される動作は、結果が予測できないことです。 sendfile()はアトミックではありません。それは、ファイルディスクリプタからread()を、ソケットディスクリプタからwrite()を呼び出す独自のループを書くことと事実上同じです。これが行われている間に他のプロセスがファイルに書き込むと、古いコンテンツと新しいコンテンツが混在します。これは主に便利な機能ですが、複数のシステムコールを必要とせず、アプリケーションバッファ間でのやりとりではなく、ファイルバッファとソケットバッファ間の直接コピーが可能であるため、はるかに効率的です。このため、脆弱性のウィンドウはread/writeループを実行するよりも小さくなるはずですが、まだそこにあります。

この問題を回避するには、書き込みを行うプロセスとsendfile()を呼び出すプロセスの間でファイルロックを使用する必要があります。だから、シーケンスは次のようになります。

lock the file 
call sendfile() 
unlock the file 

と書き込み処理を行う必要があります。

lock the file 
write to the file 
unlock the file 

EDIT:それはこの単純ではないようsendfile()ソケットを結ぶため

は実際に、それは、見えますカーネルにコピーするのではなく、ファイルバッファキャッシュにバッファリングします。 sendfile()はデータが送信されるのを待たず、返った後にファイルを変更すると送信される内容に影響を与える可能性があります。データがすべてアプリケーションレイヤの肯定応答で受信されたことを確認する必要があります。これらの詳細について説明している記事の抜粋については、Minimizing copies when writing large data to a socketを参照してください。

+0

mmapが同じように動作するかどうか知っていますか? void * p = mmap(fd0); send(fd1、p、0、len)。したがって、データが確実に送信される方法はありませんか?私は再び安全にファイルを編集することを意味します。一つの方法は、しかし、クライアントに頼っているかもしれない。これに関するアイデア? – vkx

+0

'send()'や 'sendfile()'が返ってきたら、すべてのデータがソケットバッファにコピーされたと思いますので、ファイルを変更しても安全です。私はあなたが 'sendfile()'を呼んでいるときに同時にファイルを修正する別のプロセスを使っていたと思いました。 – Barmar

+0

send()はそのように動作しますが、私はこのリンクを見つけました。受け入れられた答えはsendfileとmmapは異なっていますが、答えの元の紙のリンクがうまくいきません。 私はこの動作がわかりません。 https://stackoverflow.com/questions/20008707/minimizing-copies-when-writing-large-data-to-a-socket – vkx

関連する問題