5

同じファイルに作用する 2 つのプロセスがある場合があります。1 つはライターとして、もう 1 つはリーダーです。ファイルは 1 行のテキスト ファイルで、ライターはループ内でその行を書き直します。リーダーは行を読み取ります。擬似コードは次のようになります。

ライター プロセス

char buf[][18] = {
"xxxxxxxxxxxxxxxx",
"yyyyyyyyyyyyyyyy"
};
i = 0;
while (1) {
 pwrite(fd, buf[i], 18, 0);
 i = (i + 1) % 2;
}

読者のプロセス

while(1) {
  pread(fd, readbuf, 18, 0);
  //check if readbuf is either buf[0] or buf[1]
}

readbuf両方のプロセスをしばらく実行した後、 が または のいずれかxxxxxxxxxxxxxxxxyyであることがわかりましたyyyyyyyyyyyyyyyyxx

私の理解では、書き込みは最大 512 バイトのサイズでアトミックになるということでした。しかし、私の実験では、アトミック性は 16 バイトのみのようです。

man ページには、通常のファイルのアトミック性については何も記載されていません。512 バイトのパイプのアトミック性についてのみ言及されています。

tmpfs と ext4 でこれを試しましたが、結果は同じです。を使用するとO_SYNC、ext4 の書き込みがアトミックになり、ディスクにヒットするまで書き込みが返されないため、理解できO_SYNCますが、tmpfs ( /dev/shm) には役立ちません。

4

2 に答える 2

4

POSIX では、パイプへの書き込みを除きread、アトミック操作の最小保証はありません(最大(512) バイトまでの書き込みはアトミックであることが保証されますが、読み取りにはアトミック性の保証はありません)。との操作はバイト値で説明されています。パイプを除けば、操作はシングルバイト操作のループと比較して追加の保証を提供しません。writePIPE_BUFreadwritewritewrite

16 でも 512 でも、Linux が提供する追加の保証については知りません。実際には、カーネルのバージョン、ファイルシステム、およびおそらく基礎となるブロック デバイス、 CPU の数、CPU アーキテクチャなど。

、および保証 (およびPOSIXのオプションのSIO機能で指定されたO_SYNC同期された I/O データの整合性の完了) は、必要なものではありません。またはシステム コールの前に書き込みが永続ストレージにコミットされることを保証しますが、操作の進行中に開始されるについては主張しません。O_RSYNCO_DSYNCreadwritereadwritewriteread

あなたのシナリオでは、ファイルの読み取りと書き込みは適切なツールセットのようには見えません。

  • 少量のデータのみを転送する必要がある場合は、パイプを使用してください。コピーについてあまり心配する必要はありません。メモリ内のデータのコピーは、ほとんどの処理またはコンテキスト スイッチの規模で非常に高速です。さらに、Linux はコピーの最適化が得意です。
  • 大量のデータを転送する必要がある場合は、おそらく何らかの形式のメモリ マッピングを使用する必要があります。ディスク バッキングが必要ない場合は共有メモリ セグメントを使用するか、必要な場合は共有メモリ セグメントを使用しますmmap。これは原子性の問題を魔法のように解決するわけではありませんが、適切な同期メカニズムのパフォーマンスを向上させる可能性があります。同期を実行するには、次の 2 つの基本的な方法があります。
    • プロデューサは共有メモリにデータを書き込み、利用可能なデータを正確に示す通知をコンシューマに送信します。コンシューマーは、要求があった場合にのみデータを処理します。通知は、同じチャネル (例: mmap+ msync) または別のチャネル (例: パイプ) を使用できます。
    • プロデューサはデータを共有メモリに書き込み、書き込みをフラッシュします (例: msync)。次に、プロデューサは既知の値を 1 つのマシン ワードに書き込みます (a のsig_atomic_tアトミック性は正式にはシグナルに対してのみ保証されていますが、実際には auintptr_tです)。コンシューマはその 1 つのマシン ワードを読み取り、このワードに許容可能な値がある場合にのみ、対応するデータを処理します。
于 2016-02-24T00:54:05.670 に答える