15

私はinotify呼び出しを研究してきましたが、読み取りインターフェイスに関してはまだ少し不安定です。これらは、read(2)を使用してinotifyと適切にインターフェイスする方法に関して私が見つけた最も関連性の高いリソースです。

どちらも同じ方法で実装し、最初に次のサイズを定義します。

#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 )

そして、彼らはこれらを次のように使用します。

length = read( fd, buffer, BUF_LEN );  

if ( length < 0 ) {
    perror( "read" );
}  

while ( i < length ) {
    struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
    /* some processing */
    i += EVENT_SIZE + event->len;
}

struct inotify_eventこれで、名前がの一部であり、長さが可変であることがわかりました。では、バッファ内の最後のinotify_eventを切り捨てることはできませんでしたか?

パスが16バイトのinotify_eventsが1023個あり、パスが32バイトのinotify_eventsが10個あるとします。それではどうなりますか?後で切り捨てられますか?または、カーネルはそれがバッファに収まらないことを認識し、すべてをそのままにしますか?

4

1 に答える 1

9

基本的な使い方

inotify(7)によると、FIONREAD ioctlを使用して、読み取ることができるデータの量を調べ、それに応じてバッファーのサイズを設定できます。これを実現できる(非常に大まかな)コードを次に示します。

unsigned int avail;
ioctl(inotify_fd, FIONREAD, &avail);

char buffer[avail];
read(fd, buffer, avail);

int offset = 0;
while (offset < avail) {
    struct inotify_event *event = (inotify_event*)(buffer + offset);

    // Insert logic here
    my_process_inotify_event(event);

    offset = offset + sizeof(inotify_event) + event->len;
}

より堅牢な使用法

inotify-toolsは、inotifyへのより高いレベルのインターフェースを提供します。inotifyにアクセスする代わりに使用するか、inotifytools_next_eventsを実装して、利用可能なすべてのイベントを安全かつ堅牢に読み取る方法を確認できます。

部分的なイベントと切り捨て

切り捨てに関する質問への回答として、指定されたバッファがすべてのイベントに対して小さすぎる場合、カーネルが部分的なinotify_eventを返したり、inotify_eventを切り捨てたりすることはないと思います。inotify(7)のマンページの次の段落は、これを示唆しています。

read(2)に指定されたバッファーが小さすぎて次のイベントに関する情報を返すことができない場合の動作は、カーネルのバージョンによって異なります。2.6.21より前のカーネルでは、read(2)は0を返します。カーネル2.6.21以降、read(2)はエラーEINVALで失敗します。

inotifytools.cからの次のコメントも同様です。

// oh... no.  this can't be happening.  An incomplete event.
// Copy what we currently have into first element, call self to
// read remainder.
// oh, and they BETTER NOT overlap.
// Boy I hope this code works.
// But I think this can never happen due to how inotify is written.
于 2012-11-08T20:37:46.497 に答える