You need to enable JavaScript to run this app. C语言使用inotify无法捕获第二个新建事件的问题
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.02 17:15:02