【问题标题】:Does poll/epoll block? How is it different from async IO?poll/epoll 会阻塞吗?它与异步 IO 有何不同?
【发布时间】:2011-11-04 18:16:39
【问题描述】:

我一直认为 poll/epoll 不会阻塞。这就是 Nginx 等非阻塞服务器使用它们的原因。

但在这个Stackoverflow question 中多次声明投票阻塞。

那么 poll/epoll 会阻塞吗?

poll/epoll 与异步 IO 有何不同?

【问题讨论】:

  • 选择/轮询/epoll 块。但是,它可以用于一次等待多个事件,而不仅仅是单个事件。

标签: asynchronous network-programming nonblocking epoll


【解决方案1】:

是的,poll/epoll 块。为客户端提供服务的服务器通常无法像使用 epoll 这样的 I/O 事件通知模型的服务器那样扩展。 poll 比 epoll 更老且效率更低(O(n) vs O(1))。

[更新]

Nginx 不是非阻塞的。当一个请求进来时,epoll_wait 正在等待的事件之一被通知并且对 epoll_wait 的调用返回。然后 Nginx 循环通过为每个事件服务的信号事件。 Nginx 源代码在这里可用...http://nginx.org/download/nginx-1.1.1.tar.gz

看一下nginx-1.1.1\src\event\modules\ngx_epoll_module.c中的ngx_epoll_process_events函数

[更新2]

另请参阅 epoll_wait(2) 的手册页 ...http://linux.die.net/man/2/epoll_wait

#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

指定 -1 的超时时间使 epoll_wait(2) 无限期地等待, 同时指定一个等于零的超时使 epoll_wait(2) 返回 即使没有事件可用也立即(返回码等于 零)。

[更新3]

要向自己证明 Nginx / epoll 会阻塞,请在 Linux 上试试这个...

  1. 下载源代码并取消归档
  2. cd 到源目录
  3. ./configure --with-debug(注意:我必须添加 libpcre3-dev)
  4. make
  5. sudo make install
  6. 启动 nginx:/usr/local/nginx/sbin/nginx(注意:我必须先杀死 apache sudo /etc/init.d/apache2 stop
  7. sudo gdb
  8. file /usr/local/nginx/sbin/nginx
  9. b ngx_epoll_module.c:531(设置断点)
  10. 在另一个终端窗口中,ps -ef | grep nginx 并使用 nginx 工作进程(不是主进程)的 PI​​D
  11. 回到 gdb,attach &lt;PID of nginx worker&gt;
  12. continue 恢复进程

您可能需要continue 几次,但它最终应该会被阻止。然后打开浏览器并转到http://localhost ...然后调试器应该在epoll_wait 返回后立即中断。

【讨论】:

  • 如果epoll阻塞,使用epoll的服务器(例如Nginx)如何变成非阻塞的?
  • 感谢您的更新。那么如果 Nginx 是阻塞的,它与像 Apache 这样也阻塞的服务器有什么不同呢?此外,epoll 的手册页(linux.die.net/man/4/epoll)谈到了非阻塞使用:“epoll 接口,当与 EPOLLET 标志(边缘触发)一起使用时,应该使用非阻塞文件描述符以避免阻塞读取或写入饿死处理多个文件描述符的任务。”我错过了什么?
  • 继续:epoll_wait() 本身就是一个阻塞接口。每当你调用 epoll_wait() 时,它都会阻塞你的线程/进程,直到任何被监视的事件发生在注册的描述符上。手册页讨论了 epoll 对非阻塞 FD 的使用,这是 epoll 监控的,而不是 epoll 本身。换句话说,如果你使用 EPOLLET,你应该只在 epoll 上注册非阻塞 FD。无论如何,无论你要求 epoll 监控一个非阻塞或阻塞 FD,epoll 接口本身仍然是基于阻塞的
  • 您可以通过将超时值设置为 0 来将 epoll_wait() 用作非阻塞接口。
  • @Continuation Apache 将处理与新进程/线程的连接,这将阻塞。例如,1000 个线程被阻塞等待响应。相比之下,Nginx 会使用 epoll 注册 1000 个连接。但是,如果与这 1000 个连接无关,它将阻塞。当一个事件发生时,它将继续。但是要做到这一点,您只需要一个线程,而不是一千个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-01
  • 1970-01-01
  • 2014-09-25
  • 2012-01-15
  • 2018-11-07
  • 1970-01-01
  • 2018-04-06
相关资源
最近更新 更多