2 つのプロセス (リーダーとライター) が、ext3 ファイル システム上の通常のファイルを介して通信しているとします。リーダーは、IN_MODIFY
ファイルに対して inotify 監視機能を持っています。ライターは、1 回の呼び出しで、ファイルに 1000 バイトを書き込みますwrite()
。リーダーは inotify イベントを取得し、fstat
ファイルを呼び出します。リーダーは何を見ているのでしょうか?
st_size
Reader がファイルに対して少なくとも 1000 を返すという保証はありますか? 私の実験では、そうではないようです。read()
Reader が実際に1000 バイトに対応できるという保証はありますか?
これは、深刻な I/O バウンド ボックスで発生します。たとえば、sar
約 1 秒の待機時間が表示されます。私のケースでは、Reader は実際には inotify イベントを取得してから を呼び出すまで 10 秒待機しておりstat
、結果が小さすぎます。
私が期待していたのは、ファイルの準備ができるまで inotify イベントが配信されないことでした。実際write()
には、inotify イベントは Writer の呼び出し中に発生し、データが準備できたときにシステム上の他のプロセスで実際に利用可能になっているのではないかと考えています。この場合、10 秒では時間が足りません。
おそらく、私が探しているのは、カーネルが実際に私が推測した方法で inotify を実装しているかどうかの確認だけです。また、この動作を変更するためのオプションはありますか?
最後に、このような動作を考えると、inotify の意味は何でしょうか。イベントを取得した後、データが実際に利用可能になるまで、ファイル/ディレクトリをポーリングすることになります。ずっとそれを実行して、inotify を忘れたほうがよいでしょう。
***編集**** さて、よくあることですが、私が実際に何をしているのかがわかったので、私が見ている動作は実際に意味をなしています。^_^
実際には、ファイルが存在するディレクトリの IN_CREATE イベントに応答しています。したがって、実際には、ファイルの作成に応答してファイルの stat() を実行しており、後で到着する可能性のある IN_MODIFY イベントに応答しているわけではありません。
コードを変更して、IN_CREATE イベントを取得したら、ファイル自体の IN_MODIFY をサブスクライブし、IN_MODIFY イベントを取得するまで実際にファイルの読み取りを試行しないようにします。ファイルへの書き込みを見逃す可能性のある小さなウィンドウがあることは認識していますが、最悪の場合でも、ファイルは最大数秒後に閉じられるため、これは私のアプリケーションでは許容範囲です。
答え1
私が見たところカーネルソースでは、inotifyは書き込みが完了した後にのみ起動します(つまり、あなたの推測は間違っています)。通知がトリガーされた後、システムコールsys_write
を実装する関数ではwrite
、スケジューラパラメータの設定とファイル記述子の位置の更新という2つのことだけが行われます。このコードは、2.6.14通知が送信されるまでに、ファイルのサイズはすでに新しいサイズになっています。
問題が発生する可能性がある項目を確認します。
- おそらく読者は、前回の書き込みからの古い通知を受け取っているのでしょう。
- リーダーが を呼び出してから を呼び出す場合
stat
、read
またはその逆の場合、その間に何かが起こる可能性があります。ファイルに追加し続ける場合、stat
最初に を呼び出すと、そこまで読み取ることができることが保証されますが、リーダーが を呼び出すまでにread
、inotify 通知をまだ受け取っていなくても、さらにデータが書き込まれている可能性があります。 - ライターが呼び出したからといって、
write
カーネルが要求された文字数を書き込むとは限りません。任意のサイズまでアトミック書き込みが保証される状況はほとんどありません。write
ただし、各呼び出しはアトミックであることが保証されています。ある時点ではまだデータが書き込まれておらず、その後突然んバイトが書き込まれ、んは呼び出しの戻り値ですwrite
。部分的に書き込まれたファイルを見つけた場合、それはwrite
サイズ引数よりも小さい値が返されたことを意味します。
何が起こっているかを調査するのに役立つツールは次のとおりです。
strace -tt
- 監査サブシステム