【问题标题】:How do I use epoll?如何使用 epoll?
【发布时间】:2015-07-05 13:12:59
【问题描述】:

我知道在 epoll_ctl 中注册了对文件描述符的兴趣,但我找不到任何有关如何实际使用 epoll 的信息。

如果我想异步读写文件,我该怎么做?我是否使用正常的读写调用?我是在调用 epoll_wait 之前还是之后调用这些函数,是否将文件描述符标记为非阻塞?

【问题讨论】:

  • linux.die.net/man/4/epoll哪个部分你不明白?一般来说,对于每个函数,你可以`man func_name 来阅读它。
  • 关于你的异步 io 东西。如果epoll 将 fd 返回给您。它保证是非阻塞的。我不明白你在担心哪一点。

标签: linux


【解决方案1】:

您正在混淆这些概念。 epoll(7) 与异步 I/O 不同。 select(2)poll(2)epoll(7)等类似函数,无论底层文件描述符是阻塞还是非阻塞,都可以阻塞;它们提供同步形式的通知 - 在您明确要求之前,系统不会告诉您任何信息。

select(2)poll(2) 和系列的要点是您可以进行 I/O 多路复用:通过单个阻塞调用,您可以等待给定文件描述符集中的有趣事件。这与异步 I/O 相同。

另一方面,POSIX 异步 I/O 使用 AIO 控制块来描述 I/O 操作 (struct aiocb),它主要使用 aio_read(3)aio_write(3)aio_return(3) 和 @987654331 执行@。除非您有充分的理由这样做,否则不要这样做 - 这会使设计变得相当复杂。

要使用epoll(7),除了man 7 epoll能读到的东西,真的没什么好说的了:

  • 使用epoll_create(2) 或更新的变体epoll_create1(2) 创建epoll 实例。
  • 通过epoll_ctl(2)注册对文件描述符的兴趣。
  • 调用 epoll_wait(2) 以等待 I/O 事件,可能会阻塞调用线程,直到某些事件可用

一旦epoll_wait(2) 返回,假设它成功,您可以保证至少有一个您之前在epoll_ctl(2) 注册的感兴趣的操作不会被阻止。 epoll_wait(2) 在您提供给它的缓冲区中返回不会阻塞的事件(epoll_wait(2) 的第二个参数)。

遍历该缓冲区并找出您想要做什么。例如,如果您注册了对读取文件描述符的兴趣并且它由epoll_wait(2) 返回(该条目的events 字段包括EPOLLIN),那么您可以调用read(2) 知道它不会阻塞。 write(2) 也是如此,但前提是您有兴趣知道 write(2) 何时不会阻塞,并且该事件由 epoll_wait(2) 返回。

所以,是的,您在epoll_wait(2) 之后调用read(2) / write(2),但请确保您执行的操作实际上被识别为可用,这样您就不会阻塞。

哦,请记住 epoll(7) 是特定于 Linux 的。

【讨论】:

  • 谢谢,你说得对,我混淆了一些概念。因此,例如在没有 posix 的情况下对多个文件进行异步读取,我会使用 epoll_wait (在这里阻塞很好)来等待文件描述符准备好读取。然后我会阅读那些可用的,确保文件描述符设置了 O_NONBLOCK 以便读取操作不会阻塞,然后我会再次 epoll_wait 等待读取结果?类似的东西?
  • @Storm 你快到了。致电epoll_wait(2) 后,您会阅读可用的内容。描述符不一定需要O_NONBLOCK。您遍历事件数组并测试每个条目的events 字段是否包含EPOLLIN。如果是这样,则无论描述符是否处于非阻塞模式,都可以保证读取不会阻塞,因为数据可供读取。因此,简而言之,您只需致电epoll_wait() 并阅读,就知道您无法阻止。没有第二个epoll_wait() 来“等待结果”。
  • @Storm 请注意,struct epoll_eventevents 字段是一个描述多个事件的位集,因此要测试它是否可以读取,您需要 if (ep_events.events & EPOLLIN) { /* Safe to read... */ },假设 ep_eventsepoll_wait(2) 返回的数组。
  • 是的,但是数据可能需要一些时间来读取,并且在高吞吐量服务器上例如不使用每个连接的线程我想同时在同一个线程上做其他事情,因此O_NONBLOCK。我会使用 epoll_wait 告诉我读取何时完成。
  • @Storm 如果阅读本身太昂贵,epoll 不会有太大帮助。 O_NONBLOCK 也无济于事,因为它控制 read(2) 是否阻塞 waiting 数据。如果数据可以读取,读取它总是需要一些时间,你必须等待。如果您想在阅读时在同一个线程中执行操作,那么您几乎会被 POSIX 异步 I/O 所困扰(更具体地说,aio_read(3))。请参阅 man 7 aioman 3 aio_read。请注意,异步 I/O 本身就很难正确处理,请确保确实没有其他选择。
猜你喜欢
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多