C语言使用inotify无法捕获第二个新建事件的问题
目录监测代码的问题定位与修正
核心问题根因
- 最致命的执行流错误:调用线程创建函数时,直接执行了线程函数本身而非传入函数指针
原代码中pthread_create(&inotify_pthread, NULL, event_read_data(),NULL)的写法,会在执行到该行时直接进入event_read_data的死循环,根本不会触发pthread_create的调用,直接导致主程序卡在子函数死循环,无法回到监听循环处理后续事件。 - 事件遍历逻辑错误:首次遍历inotify事件时使用了未初始化的
event指针值计算偏移步长,会导致越界、解析错事件。 - 变量类型定义错误:
wd本意是存储inotify_add_watch返回的整型监控符,却被定义成整型指针,后续还执行了无意义的free(wd)操作,触发未定义行为struct pollfd fds[0]是零长度数组,无法存储poll需要的监控描述符,越界写入内存
- 线程接口不匹配:
event_read_data没有定义符合pthread要求的void* 函数名(void*)返回值与参数形式,属于未定义行为 - 缺失头文件:未引入
<pthread.h>声明,编译器对pthread接口的隐式声明会导致运行异常
修正后可运行的代码
#include <errno.h> #include <poll.h> #include <stdio.h> #include <stdlib.h> #include <sys/inotify.h> #include <unistd.h> #include <string.h> #include <pthread.h> #define PATH_MAX 4096 // 符合pthread规范的线程函数:返回值void*,入参void* void* event_read_data(void* arg) { // 设置线程分离,避免资源泄漏 pthread_detach(pthread_self()); while(1) { printf("Child Thread running, tid = %lu\n", pthread_self()); sleep(3); } return NULL; } int main() { char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event)))); int fd, poll_num; int wd; nfds_t nfds; struct pollfd fds[1]; char *device_path = "/home/home/test"; ssize_t len; const struct inotify_event *event; int counter = 0; int thread_ret = 0; pthread_t inotify_pthread; /* 初始化inotify实例 */ fd = inotify_init1(IN_NONBLOCK); printf("inotify fd = %d\n", fd); if (fd == -1) { perror("inotify_init1"); exit(EXIT_FAILURE); } /* 绑定目录监控事件:新建、删除 */ wd = inotify_add_watch(fd, device_path, IN_CREATE | IN_DELETE); printf("watch descriptor = %d\n", wd); if (wd == -1) { fprintf(stderr, "Cannot watch '%s': %s\n", device_path, strerror(errno)); exit(EXIT_FAILURE); } /* 初始化poll监控 */ nfds = 1; fds[0].fd = fd; fds[0].events = POLLIN; printf("Listening for events.\n"); while (1) { poll_num = poll(fds, nfds, -1); if (poll_num == -1) { if (errno == EINTR) continue; perror("poll"); exit(EXIT_FAILURE); } if (poll_num > 0) { if (fds[0].revents & POLLIN) { len = read(fd, buf, sizeof(buf)); if (len == -1 && errno != EAGAIN) { perror("read"); exit(EXIT_FAILURE); } if (len <= 0) break; // 修正事件遍历逻辑:每次基于当前解析的event计算下一个事件的偏移 char *ptr = buf; while (ptr < buf + len) { event = (struct inotify_event *) ptr; // 只有带文件名的事件才处理 if (event->len > 0) { if (event->mask & IN_CREATE) { counter++; printf("IN_CREATE: created file = %s, counter = %d \n", event->name, counter); // 修正:传函数指针而非直接调用函数 thread_ret = pthread_create(&inotify_pthread, NULL, event_read_data, NULL); if (thread_ret != 0) { printf("can't create inotify thread, err = %d\n", thread_ret); exit(EXIT_FAILURE); } } else if (event->mask & IN_DELETE) { counter--; printf("IN_DELETE: deleted file = %s, counter = %d \n", event->name, counter); } } // 基于当前event的长度计算下一个事件的偏移 ptr += sizeof(struct inotify_event) + event->len; printf("current counter = %d \n", counter); } } } } printf("Listening for events stopped.\n"); close(fd); exit(EXIT_SUCCESS); }
编译命令保持不变:
gcc file_name.c -lpthread
内容的提问来源于stack exchange,提问作者GNK
相关产品推荐
相关产品推荐

