inotify 中, 在 read 其 struct inotify_event 时, 缓冲区必须大于读取的结构体的大小

本文深入探讨了Linux中inotify提供的监控文件变化的功能,包括inotify_init(), inotify_add_watch() 和 inotify_rm_watch() 函数的使用。详细解析了inotify事件结构及其特性,以及如何有效地读取和处理这些事件。

 linux中监控文件的 inotify 提供了以下几个编程函数, inotify_init(), inotify_add_watch(), 

inotify_rm_watch(). 从 inotify_init() 返回的文件描述符 read, 读取监听到的事件. 

事件的结构为:

 struct inotify_event {
             int      wd;       /* Watch descriptor */
             uint32_t mask;     /* Mask of events */
             uint32_t cookie;   /* Unique cookie associating related
                                   events (for rename(2)) */
             uint32_t len;      /* Size of ’name’ field */
             char     name[];   /* Optional null-terminated name */
         };
因为每个文件名的长度不定, 所以每个事件占用的内存大小也不一定相等.

假设 EVENT_LEN = sizeof(sturct inotify_event),  NAME_LEN = len (事件结构体中的len, 为保持内存对齐, 可能大于 strlen(name));

假设inotify的事件队列中有很多未读取的, 读取事件 ret =  read(fd, buf, BUF_LEN);  

如果 BUF_LEN < EVENT_LEN + NAME_LEN,   ret = 0;

如果 EVENT_LEN + NAME_LEN <= BUF_LEN < 2 * (EVENT_LEN + NAME_LEN ), ret = EVENT_LEN + NAME_LEN;

如果 2 * (EVENT_LEN + NAME_LEN)  <= BUF_LEN < 3* (EVENT_LEN + NAME_LEN _, ret = 2 * (EVENT_LEN + NAME_LEN );

  ......

也就是, 只能整个的读取 struct inotify_event, 不能读取部分结构.

- - - - - - - -

以上是我个人的测试.

#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/epoll.h> #include <sys/inotify.h> #include <linux/input.h> #define EVENT_SIZE (sizeof(struct inotify_event)) #define BUF_LEN (1024 * (EVENT_SIZE + 16)) #define MAX_EVENTS 1024 void read_input_events(int fd) { struct input_event ev; while (read(fd, &ev, sizeof(ev)) == sizeof(ev)) { if (ev.type != EV_SYN) { printf("Event: time %ld.%ld, type %d, code %d, value %d\n", ev.time.tv_sec, ev.time.tv_usec, ev.type, ev.code, ev.value); } } } int add_input_device_to_epoll(int epoll_fd, const char *dev_name) { char path[256]; snprintf(path, sizeof(path), "/dev/input/%s", dev_name); int fd = open(path, O_RDONLY | O_NONBLOCK); if (fd == -1) { perror("open"); return -1; } struct epoll_event event; event.events = EPOLLIN; event.data.fd = fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event) == -1) { perror("epoll_ctl"); close(fd); return -1; } return fd; } int main() { int epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (epoll_fd == -1) { perror("epoll_create1"); exit(EXIT_FAILURE); } int inotify_fd = inotify_init(); if (inotify_fd == -1) { perror("inotify_init"); close(epoll_fd); exit(EXIT_FAILURE); } int watch_fd = inotify_add_watch(inotify_fd, "/dev/input", IN_CREATE | IN_MODIFY | IN_DELETE); if (watch_fd == -1) { perror("inotify_add_watch"); close(inotify_fd); close(epoll_fd); exit(EXIT_FAILURE); } struct epoll_event event; event.events = EPOLLIN; event.data.fd = inotify_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, inotify_fd, &event) == -1) { perror("epoll_ctl"); close(inotify_fd); close(epoll_fd); exit(EXIT_FAILURE); } char buffer[BUF_LEN]; struct epoll_event events[MAX_EVENTS]; while (1) { int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (num_events == -1) { perror("epoll_wait"); break; } for (int i = 0; i < num_events; ++i) { int fd = events[i].data.fd; if (fd == inotify_fd) { int length = read(inotify_fd, buffer, BUF_LEN); if (length < 0) { perror("read"); continue; } int offset = 0; while (offset < length) { struct inotify_event *event = (struct inotify_event *)&buffer[offset]; if (event->mask & IN_CREATE && event->len) { add_input_device_to_epoll(epoll_fd, event->name); } offset += EVENT_SIZE + event->len; } } else { read_input_events(fd); } } } inotify_rm_watch(inotify_fd, watch_fd); close(inotify_fd); close(epoll_fd); return 0; } 解析这段代码
最新发布
08-08
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值