2011-08-01 7 views
6

私は大量のデータを書き込む2つのプロセスを持っており、これらのプロセスの1つのファイルへの書き込みを同期させて制御したいと考えています。 (A1、A2、A3)と(B1、B2、B3)を含む処理2書き込みバッファBを含む処理1書き込みバッファA。 write()システムコールを使用して、これらのバッファを同じファイル(一度に全バッファ:write(fd, A, sizeof(A)))にディスクに書き込むと、ファイルスキーマはどのようになりますか?2つのプロセスの1つのファイルにアトミック書き込みを同期させるにはどうすればよいですか?

  • A、BまたはB、Aのようなものでしょうか?
  • か、それはこのようなことができます:システムコールはアトミックであるため、A1、A2、B1、A3、...

私はこれを聞いていますのよ。私たちが書き込んでいるデータバッファが大きすぎるとどうなりますか?それは普通のディスクファイル用のパイプのようなものですか?

答えて

4

あなたは両方のバッファの内容が存在するようにしたい場合は、開く必要がありますO_APPENDフラグが設定されたファイル。 appendフラグは、書き込みの前にファイルの終わりを探します。このセットがなければ、両方のプロセスがファイルの同じまたは重複する領域を指している可能性があり、最後に書き込むと誰かが書き込んだものを上書きしてしまう可能性があります。

writeを呼び出すたびに、要求されたバイト数が書き込まれます。プロセスがシグナルによって中断された場合、部分的な書き込みで終了することができます - 実際に書き込まれたバイト数が返されます。あなたのバイトのすべてが書かれているかどうかにかかわらず、ファイルの1つの連続したセクションが書かれます。 2番目の可能性(A1、B1、A2、B2、...など)として説明したインターリーブ効果は得られません。

一部の書き込みしか得られない場合、どのように進むかはあなた次第です。書き込みを続行するか(以前に書き込まれたバイト数でバッファの先頭からオフセットする)、残りの書き込みを中止することができます。この方法でのみインターリーブ効果を得ることができます。

他のプロセスが書き込む前に1つの書き込みの内容を完了させることが重要な場合は、データの書き込みを試みる前に、排他書き込みアクセス(両方のプロセスがチェックする必要があります)をロックする必要があります。

+0

信号がないので、 'O_APPEND'が有効になっていれば、A、BまたはB、Aを持つ必要があります。私は正しい? –

+1

@マジド - はい、システム上の何もあなたを妨害しないと仮定すると、誰が最初に行くかに応じて、A、BまたはB、Aを得るでしょう。 – unpythonic

+0

ローカルファイルシステム上の通常のファイルへの書き込みが中断されることはありません。 NFSには中断可能にするフラグがありますが、デフォルトはオフです。 –

2

バッファのサイズが同じであると仮定すると、最後にスケジュールされたプロセスに応じて、結果はAまたはBのいずれかになります。

writeシステムコールはアトミックであり、結果はAまたはBのいずれかであり、両方の混合ではありません。

ファイルにAとBの両方が必要な場合は、O_APPENDでファイルを開くことができます。ただし、これはNFS上では動作しません。

別のオプションは、各プロセスが使用すべきオフセットされたファイルを追跡していることである、と(のlseekを使用しています)またはPWRITE()

2

ファイルにアクセスするプログラムには、何らかの形式の同期が必要です。そうしないと、ファイルの内容が乱れることがあります。 writeシステムコールでは、要求されたバイト数より少ないバイト数しか書き込めないため、ブロックA1、A2またはB1、B2は部分的にしか書き込まれません。これは、多くの状況によっては頻繁に起こることもあれば、まれに起こることもあります。 1週間に1回しか発生しない場合は、検出が非常に難しいバグがあります。

解決策として、ファイルロック(man 2 flockまたはman fcntlとロックを検索)を使用できます。もう1つの可能性は、セマフォー(man -k semaphore)を使用して、プログラム書き込みまたは他の形式のIPCを同期させることです。

+0

+1すべてのファイルを一度に書き込むのは効率が悪い(または難しい)ことが多いため、おそらくファイルロッキングが必要です。 –

関連する問題