有人可以向我解释事件驱动的IO系统调用如select,poll和epoll如何与阻塞与非阻塞IO相关联?
我不明白如何相关 - 如果有的话,这些概念是
答案 0 :(得分:6)
它们在很大程度上是不相关的,除了您可能希望将非阻塞文件描述符与事件驱动的IO一起使用,原因如下:
旧版本的Linux肯定会在内核中出现错误read
即使在select
指示套接字可读之后也会阻塞(在UDP套接字和校验和错误的数据包中发生)。当前版本的Linux 可能仍然有一些这样的错误;我不确定。
如果其他进程有可能访问您的文件描述符并且会对它们进行读/写,或者如果您的程序是多线程的,而其他线程可能会这样做,则{之间存在竞争条件{1}}确定文件描述符是可读/可写的,并且程序在其上执行IO,这可能导致阻塞。
你几乎肯定想在调用select
之前使套接字无阻塞;否则你将阻止,直到建立连接。使用connect
进行写入以确定何时成功连接,并select
进行错误以确定连接是否失败。
答案 1 :(得分:5)
几乎所有Unix都支持select
系统调用,并为用户空间应用程序提供监视一组描述符的方法,并获取有关该组的哪个子集已准备好进行读/写的信息。它的特殊界面有点笨拙,大多数内核中的实现充其量只是平庸。
epoll
仅在Linux中提供用于相同目的,但在效率和编程接口方面比select
有很大改进。其他Unix也有专门的调用。
也就是说,事件驱动的IO系统调用不需要阻塞或非阻塞描述符。阻止是一种影响read
,write
,accept
和connect
等系统调用的行为。 select
和epoll_wait
确实有阻止超时,但这与描述符无关。
当然,使用带有阻塞描述符的这些事件驱动的系统调用有点奇怪,因为您可能希望在收到通知可用后立即读取数据而不会阻塞。在收到准备通知后,始终依赖阻塞描述符不会阻塞,因为竞争条件是可能的。
非阻塞,事件驱动的IO可以使服务器应用程序更加高效,因为每个描述符(连接)都不需要线程。在性能方面将Apache Web服务器与Nginx或Lighttpd进行比较,您将看到好处。
答案 2 :(得分:0)
select
和类似的函数(你提到过几个)通常用于在事件驱动的系统中实现事件循环。
当文件描述符可用时,您可以确保数据可用且read()操作不会阻止。
这是一种同时处理来自多个源的数据而无需使用多个线程的方法。