将 read 与 inotify 一起使用

发布于 2024-10-20 16:49:21 字数 1095 浏览 5 评论 0原文

我一直在研究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;
}

现在,我们知道 name 是 struct inotify_event 的一部分,并且它具有可变长度。那么,buffer中的最后一个inotify_event不能被截断吗?

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

I have been studying inotify call, but I still a bit flaky when it comes to the read interface. These are the most relevant resourses I could find regarding how to properly interface with inotify using read(2):

They both implement it in the same way, they first define the following sizes:

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

And then they use them in this manner:

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;
}

Now, we know name is part of struct inotify_event and that it has variable length. So, couldn't the last inotify_event in buffer be truncated?

Suppose there is 1023 inotify_events with a path of 16 bytes and one with a path of 32 bytes. What will happen then? Will the later truncated? Or will the kernel see that it won't fit in the buffer and leave it all altogether?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

妄想挽回 2024-10-27 16:49:21

基本用法

根据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,或者您可以查看它如何实现 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.

Basic usage

According to inotify(7), you can use the FIONREAD ioctl to find out how much data is available to be read and size your buffer accordingly. Here's some (very rough) code that can accomplish this:

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;
}

More robust usage

inotify-tools provides a higher-level interface to inotify. You can use it instead of accessing inotify, or you can see how it implements inotifytools_next_events to safely and robustly read all available events.

Partial events and truncation

In response to your questions about truncation, I do not think that the kernel will ever return a partial inotify_event or truncate an inotify_event if the buffer given is too small for all events. The following paragraph from the inotify(7) manpage suggests this:

The behavior when the buffer given to read(2) is too small to return information about the next event depends on the kernel version: in kernels before 2.6.21, read(2) returns 0; since kernel 2.6.21, read(2) fails with the error EINVAL.

As do the following comments from 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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文