11

posix 標準では、パイプまたは FIFO への PIPE_BUF バイト未満の書き込みがアトミックに許可される場合、つまり、書き込みが他のプロセスと混在しないことが指定されています。しかし、通常のファイルについて標準がどのように指定されているかを見つけることができませんでした。つまり、PIPE_BUF 未満の書き込みを行うと、アトミックも許可されるというのは本当です。しかし、通常のファイルにはそのような制限があることを知りたいですか? つまり、パイプには容量があるため、パイプに書き込み、その容量を超えると、カーネルはライターをスリープ状態にするため、他のプロセスは書き込みの機会を得ますが、通常のファイルにはそのような必要はないようです制限、そうですか?

私がやっていることは、いくつかのプロセスがログをファイルに生成することです。もちろん、O_APPEND が設定されています。

4

5 に答える 5

5

http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm (Single UNIX Specification, Version 4, 2010 Edition)からの引用:

このボリュームの POSIX.1-2008 では、複数のプロセスからファイルへの同時書き込みの動作は指定されていません。アプリケーションでは、なんらかの形式の同時実行制御を使用する必要があります。

仕様では、複数のリーダーの場合に書き込みに関する書き込みのセマンティクスがどのように発生するかについて説明していますが、上記からわかるように、複数の同時書き込みの動作は仕様では定義されていません。

上記のメモはfilesについて説明しています。パイプと FIFO の場合、PIPE_MAX セマンティクスが適用され、同時書き込みは PIPE_MAX バイトまで割り切れないことが保証されます。

パイプまたは FIFO への書き込み要求は、次の例外を除いて、通常のファイルと同じ方法で処理されます。

{PIPE_BUF} バイト以下の書き込み要求は、同じパイプで書き込みを行う他のプロセスからのデータとインターリーブされません。{PIPE_BUF} バイトを超える書き込みは、ファイル ステータス フラグの O_NONBLOCK フラグが設定されているかどうかに関係なく、他のプロセスによる書き込みと任意の境界でデータをインターリーブすることができます。

実際のファイル システムの場合、状況は複雑です。一部のローカル ファイル システムは、書き込み中にファイル ハンドルをロックすることにより、任意のサイズ (メモリ制限) までアトミックな書き込みを強制する場合があります。 /linux+v3.5.3/fs/jbd2/transaction.c#L147 )。

非ローカル ファイル システムの場合、結果は多かれ少なかれグラブになります。なんらかの形式の明示的なロックなしで、ネットワーク化されたファイル システムで同時書き込みを試みないでください (または、使用しているネットワーク ファイル システムのセマンティクスについて完全に確信している場合)。

ところで、O_APPEND は、異なるプロセスによるすべての書き込みがファイルの最後に行くことを保証します。ただし、上記の SUS が指摘しているように、書き込みが実際に同時実行される (同時に発生する) 場合、動作は未定義です。以前のユニプロセスおよびプリエンプティブでない UNIX では、これは実際には問題ではありませんでした。他の誰かが書き込む機会を得る前に write(2) の呼び出しが完了していたからです...

この質問は、オペレーティング システム (Linux?) とファイル システム (ext4?)の特定の組み合わせについて明確に答えることができます。一般的な答えは?SUSが読むように-「未定義の動作」。

于 2012-09-12T21:43:44.437 に答える
2

これはあなたにとって便利だと思います:「writev()によって書き込まれたデータは、他のプロセスの書き込みからの出力と混ざらない単一のブロックとして書き込まれる」ため、writevを使用できます

于 2012-09-12T04:04:33.377 に答える
0

原子性のすべての問題に対する究極の解決策があります。ミューテックス。ログ ファイルへの書き込みをミューテックスでラップすると、すべてがアトミックに行われます。

より簡単な解決策は、Google の GLOG ライブラリを使用することです。素晴らしいロギング システムで、私が思いついたものよりはるかに優れていて、無料で、非 GPL で、アトミックです。

于 2012-09-06T21:07:19.533 に答える
0

1 つのファイルに対する複数のライターが混同する場合があります。ただし、O_APPEND で開かれたファイルは、書き込みアクセスごとに原子的に追加されます。

下位レベルのものではなく、C stdio インターフェイスを維持したい場合は、"a" または "a+" (O_APPEND にマップされる) を使用してファイルを開き、内部に書き込む必要がないように十分な大きさのバッファーを設定します。レコードを作成し、ビルドが完了したら fsync を使用して書き込みを強制します。POSIXで保証されているかどうかはわかりません(Cはそれについて何も言いません)。

于 2012-08-24T14:47:57.850 に答える
0

それらを安全にインターリーブする 1 つの方法は、すべてのライターがファイルをロックし、書き込み、ロック解除することです。

ロックに使用できる関数は、flock()、lockf()、および fcntl() です。

すべてのライターがロックする必要があることに注意してください (そして、ロックを行うためにすべて同じメカニズムを使用する必要があります)。または、ロックを取得することを気にしないライターが、ロックを保持している別のライターと同時に書き込みを行う可能性があることに注意してください。

于 2015-12-17T04:46:11.890 に答える