2

プロデューサー/コンシューマーのセットアップがあります。クライアントはサーバーが処理するデータを提供し、クライアントは常にファイルに書き込むことでサーバーにデータを提供しています。サーバーはinotifyを使用してファイルの変更を探し、新しいデータを処理します。

問題: サーバーのファイル リーダーにはサイズ 4096 のバッファーがあります。上記の状況をシミュレートする単体テストを行いました。テストは常に開いているファイルに書き込み、ファイル リーダーは常にプロセスを読み取ろうとします。しかし、4096 よりもはるかに小さい最初のレコードが読み取られた後、ifstream オブジェクトにエラー フラグが設定されていることに気付きました。これは、到着する新しいデータが処理されていないことを意味します。簡単な回避策は、読み取りのたびに ifstream::clear を呼び出すことであり、これで問題が解決します。しかし、何が起こっているのですか?これは正しい解決策ですか?

4

2 に答える 2

1

まず、システムによっては、別のプロセスが書き込むファイルを読み取れる場合と読み取れない場合があります。 Windows では、ファイルを開くときの通常の設定ではアクセスが排他的になります。ウィンドウについては、他の設定があるかどうかを判断するのに十分な知識がありません。POSIX システムでは、適切なパーミッションを持つファイルを、異なるプロセスで読み取りおよび書き込み用に開くことができます。その音から、あなたは Linux、つまり POSIX 仕様に準拠したものを使用しています。

ただし、変更時にファイルをポーリングする方法は完全に理想的ではありません。お気づきのように、現在のファイルの最後に到達するたびに「エラー」が発生します。実際には、ファイルの末尾に到達しても実際にはエラーではありませんが、ファイルの末尾を超えて何かをデコードしようとするとエラーになります。また、ファイルの終わりを超えた読み取りは引き続き設定されるstd::ios_base::eofbitため、ストリームはgood(). このアプローチを使用することを主張する場合は、ファイルの最後まで読み取り、不完全な読み取りに何らかの方法で対処する以外に選択肢はありません。

ただし、ファイルの作成を制御できる場合は、簡単なトリックを実行できます。ファイルを通常のファイルにする代わりに、書き込みプログラムが書き込むファイル名を使用して名前付きパイプmkfifoを作成することで作成できます。 POSIX システムでファイルを開くと、新しいファイルが既に存在する場合は作成されず、既存のファイルが使用されます。まあ、ファイルやその他のものはファイル名でアドレス指定されます(ファイルと名前付きパイプに加えて、ディレクトリ、キャラクターまたはブロックの特別なデバイス、および場合によってはその他のデバイスが表示される場合があります)。

名前付きパイプは、2 つのプロセスが相互に通信することを目的とした奇妙な獣です。1 つのプロセスによって一方の端に書き込まれたものは、別のプロセスによってもう一方の端で読み取り可能です! 名前付きパイプ自体にはコンテンツがありません。つまり、ファイルのコンテンツと別のプロセスとの通信の両方が必要な場合は、コンテンツをどこかに複製する必要があるかもしれません。ファイルの現在の末尾に到達するとブロックされる読み取り用の名前付きパイプを開く。同様に、名前付きパイプへの書き込みは、リーダーが存在するまでブロックされます。それぞれのもう一方の端と通信する 2 つのプロセスが存在すると、もう一方のプロセスが終了した後に名前付きパイプの読み取りまたは書き込みを行うと、エラーが発生します。

于 2012-09-21T18:37:59.877 に答える