15

我一直在研究inotify call,但是在涉及到读取接口时我还是有点片面。这些是我能找到的关于如何使用 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 不能被截断吗?

假设有 1023 个 inotify_events,路径为 16 字节,一个为 32 字节。那时会发生什么?后期会被截断吗?或者内核会发现它不适合缓冲区并完全保留它吗?

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 回答