【问题标题】:Spurious epoll (edge triggered) notifications虚假的 epoll(边缘触发)通知
【发布时间】:2014-10-14 03:44:54
【问题描述】:

我对 epoll 和边缘触发行为的理解是,当给定文件描述符发生状态更改时,您会收到通知。即,当数据在 fd 上可用时,您会收到通知,但只有在您耗尽所有数据(您会收到 EAGAIN)并且数据再次出现后才会再次收到通知。

基于这种理解,我实现了一个服务器,它执行以下操作:

  1. 监听客户端连接
  2. 对于每个连接,将 fd 添加到 epoll 中
  3. 当数据在 fd 上可用时,产生一个单独的线程来读取直到 EAGAIN
  4. 重复直到数据读取完成

半伪代码:

n = epoll_wait(efd, events, MAXEVENTS, -1);

for (i = 0; i < n; ++i) {
    check for errors;
    if (server_sock == events[i].data.fd) {
        conn = accept( ... );
        make_nonblocking(conn);
        event.data.fd = conn;
        event.events = EPOLLIN | EPOLLRDHUP;
        epoll_ctl(efd, EPOLL_CTL_ADD, conn, &event);
    } else {
        spawn_reader(events[i].data.fd);
    }

使用上面的代码,我的期望是直到读者线程命中EAGAIN,epoll 不会为这个fd 生成另一个线程。情况似乎并非如此,我得到了许多线程。

我是否错误地使用了 epoll?每次生成阅读器线程时,我都不需要通过EPOLL_CTL_DEL 删除 fd,对吗?

【问题讨论】:

    标签: multithreading epoll


    【解决方案1】:

    是的,它可以正常工作。 epoll 允许在单线程控制(事件驱动)中进行异步 IO 编程。使用线程处理对 fd 的读取不会将其从受监视的 fd 列表中删除。

    【讨论】:

    • 感谢您的回复。我想我对 epoll 的行为还不是很清楚,但是基于实验,我认为我对什么被认为是“状态变化”的解释是不正确的?我原以为如果 fd 收到 1kB 的数据,直到我读取该数据 epoll_wait 不会再次解除阻塞,但我观察到发送的第二个 1kB 数据将解除阻塞。我猜在内核用于此连接的某个缓冲区“已满”之前,我会不断收到通知吗?
    • 对。等待和读取是完全独立的。当等待/读取在同一个控制线程中时,这不是问题。当它们在不同的线程中时,您将需要一些策略来通知阅读器线程有更多数据。或者如上所述,在等待线程中删除并添加 fds。
    猜你喜欢
    • 2016-07-08
    • 2013-01-25
    • 1970-01-01
    • 2012-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    相关资源
    最近更新 更多