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