我指的是 POSIX 标准select http://en.wikipedia.org/wiki/Select_(Unix) and poll http://linux.die.net/man/2/poll系统 C API 调用。
The select()
调用让您创建三个位掩码来标记您想要监视哪些套接字和文件描述符的读取、写入和错误,然后操作系统标记哪些实际上已经进行了某种活动;poll()
您创建了一个描述符 ID 列表,操作系统用以下标记标记每个描述符 ID:kind发生的事件。
The select()
方法相当笨拙且低效。
通常有超过一千个可供进程使用的潜在文件描述符。如果一个长时间运行的进程只打开了几个描述符,但至少其中一个已被分配了较高的数字,则将位掩码传递给select()
必须足够大才能容纳最高的描述符 - 因此数百位的整个范围将被扰乱,操作系统必须在每个select()
打电话才发现它们没有设置。
Once select()
返回后,调用者必须循环遍历所有三个位掩码以确定发生了什么事件。在许多典型应用程序中,在任何给定时刻只有一两个文件描述符会获得新流量,但必须一直读取所有三个位掩码直至最后才能发现它们是哪些描述符。
由于操作系统通过重写位掩码向您发出有关活动的信号,因此它们会被破坏,并且不再用您要侦听的文件描述符列表进行标记。您要么必须从内存中保存的其他列表重建整个位掩码,要么必须保留每个位掩码的重复副本memcpy()
每个之后的数据块位于损坏的位掩码之上select()
call.
So the poll()
方法效果更好,因为您可以继续重复使用相同的数据结构。
实际上,poll()
启发了现代 Linux 内核中的另一种机制:epoll()
这进一步改进了机制,以实现可扩展性的又一次飞跃,因为当今的服务器通常需要同时处理数万个连接。这是对这项工作的一个很好的介绍:
http://scotdoyle.com/python-epoll-howto.html http://scotdoyle.com/python-epoll-howto.html
虽然这个链接有一些很好的图表显示了好处epoll()
(你会注意到select()
到目前为止,它被认为是如此低效和过时,以至于它甚至在这些图表上都没有得到一条线!):
http://lse.sourceforge.net/epoll/index.html http://lse.sourceforge.net/epoll/index.html
Update:这是另一个 Stack Overflow 问题,其答案给出了有关差异的更多详细信息:
Twisted 中 select/poll 与 epoll 反应器的注意事项 https://stackoverflow.com/questions/2032598/caveats-of-select-poll-vs-epoll-reactors-in-twisted
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)