web-dev-qa-db-ja.com

inotifyは書き込みの開始時または完了時に通知を発行しますか?

Ext3 fs上の通常のファイルを介して通信する、リーダーとライターの2つのプロセスを想像してみてください。 Readerは、ファイルのinotify _IN_MODIFY_ウォッチを持っています。ライターは、1回のwrite()呼び出しで1000バイトをファイルに書き込みます。リーダーはinotifyイベントを取得し、ファイルに対してfstatを呼び出します。リーダーは何を見ますか?

  1. Readerがファイルの_st_size_に対して少なくとも1000を返すという保証はありますか?私の実験からはそうではないようです。

  2. 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イベントを取得するまで実際にファイルの読み取りを試行しないように、コードを変更します。ファイルへの書き込みを見逃す可能性のある小さなウィンドウがあることに気付きましたが、最悪の場合、最大秒数後にファイルが閉じられるため、これは私のアプリケーションでは許容できます。

12
Todd Freed

カーネルソース で見たところ、inotifyは書き込みが完了した後にのみ起動します(つまり、推測が間違っています)。通知がトリガーされた後、sys_writeで発生するのは、write syscallを実装する関数、スケジューラーパラメーターの設定とファイル記述子の位置の更新の2つだけです。このコードは 2.6.14 までさかのぼります。通知が発生するまでに、ファイルはすでに新しいサイズになっています。

うまくいかない可能性があることを確認します。

  • たぶん、読者は以前の書き込みからの古い通知を受け取っています。
  • リーダーがstatを呼び出してからreadを呼び出すか、またはその逆の場合、その間に何かが発生する可能性があります。ファイルに追加し続ける場合は、最初にstatを呼び出すと、その場所まで読み取ることができることが保証されますが、リーダーがreadを呼び出すまでに、さらに多くのデータが書き込まれている可能性があります。 inotify通知をまだ受信していない場合でも。
  • ライターがwriteを呼び出したからといって、カーネルが要求された文字数を書き込むことを意味するわけではありません。アトミックな書き込みが任意のサイズまで保証される状況はほとんどありません。各write呼び出しはアトミックであることが保証されています。ただし、ある時点でデータはまだ書き込まれておらず、突然nバイトが書き込まれましたここで、nwrite呼び出しの戻り値です。部分的に書き込まれたファイルを確認する場合は、writeがサイズ引数よりも少ない値を返したことを意味します。

何が起こっているのかを調査するのに役立つツールには、次のものがあります。

  • strace -tt
  • 監査されたサブシステム