使用inotify_add_watch监控目录时read()调用失败,返回errno 22
inotify监控目录时read()返回errno 22的问题排查与解决
你在使用inotify_add_watch()监控目录时遇到read()调用失败并返回errno 22(对应EINVAL,无效参数),但监控单个文件时IN_MODIFY事件能正常工作。结合你提供的代码,主要有几个明确的错误导致了这个问题:
- 变量拼写错误:
read()调用里的file_d是笔误,应该是你定义好的file_fd。这个错误会让read()拿到一个未定义的垃圾文件描述符,直接触发EINVAL错误。 print函数误用:C语言里没有print()函数,要改成printf()。- 缓冲区大小不足:监控目录时,
inotify_event结构体末尾会携带变长的name字段(记录触发事件的文件名),直接用sizeof(struct inotify_event)作为read()的缓冲区大小,会导致无法容纳完整的事件数据,后续也可能引发错误。正确做法是分配一个足够大的缓冲区,比如sizeof(struct inotify_event) + NAME_MAX + 1,确保能装下完整事件。
修复后的代码如下:
#define FILE_DIR "/etc/folder" #define FILENAME "/etc/folder/file" #include <stdio.h> #include <unistd.h> #include <sys/inotify.h> #include <errno.h> #include <string.h> #include <limits.h> // 引入NAME_MAX的定义 // 定义足够大的缓冲区,容纳inotify_event结构体和最长文件名 char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; void notify() { int file_fd = -1; int file_wd = -1; ssize_t readRet = -1; file_fd = inotify_init(); if (-1 == file_fd) { perror("inotify_init failed"); return; } file_wd = inotify_add_watch(file_fd, FILE_DIR, IN_CREATE | IN_DELETE); if (-1 == file_wd) { perror("inotify_add_watch failed"); close(file_fd); return; } // 使用足够大的缓冲区读取事件 readRet = read(file_fd, buf, sizeof(buf)); if (-1 == readRet) { printf("Error %d: %s\n", errno, strerror(errno)); close(file_fd); return; } else { printf("Read ok, %zd bytes read\n", readRet); // 解析并输出事件信息 struct inotify_event *ev = (struct inotify_event *)buf; if (ev->mask & IN_CREATE) { printf("File created: %s\n", ev->len ? ev->name : "unknown"); } else if (ev->mask & IN_DELETE) { printf("File deleted: %s\n", ev->len ? ev->name : "unknown"); } } // 清理资源 inotify_rm_watch(file_fd, file_wd); close(file_fd); }
额外提醒:要确保你对/etc/folder目录有读权限,inotify_add_watch()需要目标目录的读权限才能正常工作。如果目录不存在或权限不足,inotify_add_watch()会直接失败,但你当前的问题核心还是代码里的拼写错误和缓冲区问题。
内容的提问来源于stack exchange,提问作者dhon2407
相关产品推荐
相关产品推荐

