epoll 返回 0 个事件

Posted

技术标签:

【中文标题】epoll 返回 0 个事件【英文标题】:epoll returning with 0 events 【发布时间】:2012-12-24 03:55:16 【问题描述】:

我有两个文件描述符,一个在管道上读取文件描述符,另一个是套接字连接描述符。它们都不是非阻塞的。它们都通过单个 EPOLLIN 事件添加到 epoll 上下文中。最后,我用 timeout = -1 调用 epoll_wait。下面是示例代码。我有 两个问题:-

    管道和连接描述符是否需要非阻塞。这不是边沿触发的。如果是,这是良好做法还是强制性的,如果是强制性的,为什么?

    我将 timeout 设置为 -1,但 epoll_wait 立即返回,返回值为 0。为什么会这样?超时时间为 -1,epoll_wait 应该仅在有事件时返回。

    int total_fd_ready = -1;
    struct epoll_event pipe_event, connection_event, total_events[64];
    
    pipe_event.data.fd = pipe_fd[0];
    piple_event.events = EPOLLIN;
    connection_event.data.fd = conn_fd;
    connection_event.events = EPOLLIN;
    
    total_fd_ready = Epoll_wait(epoll_fd, total_events, 64, -1);
     printf("%d\n", total_fd_ready);
    

    epoll_wait 定义为

    int Epoll_wait(int e_fd, struct epoll_event *events, int max_events, int timeout)
    
    #ifdef DBG
            printf("Epoll_wait called on epoll_fd: %d with max_events: %d and timeout: %d\n", e_fd, max_events, timeout);
    #endif
    
    int result = -1;
    if(result = (epoll_wait(e_fd, events, max_events, timeout)) < 0)
            if(errno != EINTR)
                    err_sys("epoll_wait error with epoll fd: %d and timeout : %d\n", e_fd, timeout);
            #ifdef DBG
            else
                    printf("epoll_wait was interrupted\n");
            #endif
    return result;
    
    

更新: 发现了问题,虽然我无法解释为什么结果设置为 0。我需要在下面的 if 语句中使用括号

 if((result = (epoll_wait(e_fd, events, max_events, timeout))) < 0)

【问题讨论】:

如何声明和初始化total_events 用它更新了代码 如果编译时启用了警告,例如使用gcc -Wall,编译器会适当地警告你 【参考方案1】:

答案是比较运算符&lt; 的优先级高于赋值,这意味着result 被赋值为表达式(epoll_wait(e_fd, events, max_events, timeout)) &lt; 0 的结果。

【讨论】:

啊,有道理,谢谢!!你知道我是否需要让我的文件描述符非阻塞才能使 epoll 工作吗?我不明白为什么对于边缘触发的场景,文件描述符应该是非阻塞的 因为你不知道你对read(2) 的下一次调用是否会阻塞,完全违背了epoll(7) 的多路复用特性。 如果 epoll 返回带有 EPOLLIN 事件的套接字描述符,为什么会调用读取块?通常,我为读取事件注册套接字 fd,然后当 epoll_wait 返回时,我检查套接字 fd 是否是“事件”的一部分,如果是,那么它不应该阻塞。即使超时时间为 0,也会检查返回的“事件”是否包含要读取的套接字。 因为在边缘触发的设置中,您应该阅读直到获得EAGAIN,而阻塞描述符则无法做到这一点。 @NikolaiNFetissov 这在哪里是强制性的? EAGAIN 与读取的非阻塞方面有关。事实上,我有阻止读取和边缘触发的工作示例。我知道我应该读取的数据的大小,比如 1KB。如果 read 返回部分数据,我只需读取部分数据并等待 epoll_wait 使其再次可读。

以上是关于epoll 返回 0 个事件的主要内容,如果未能解决你的问题,请参考以下文章

epoll_wait() 是不是一次返回一个事件?

Nginx epoll模型详解

UDT中epoll对CLOSE状态的处理

UDT中epoll对CLOSE状态的处理

「底层原理」epoll源码分析,还搞不懂epoll的看过来

ThreadX内核源码分析 - 事件