我看过很多比较,都说 select 必须遍历 fd 列表,这很慢。但为什么 epoll 不必这样做呢?
最佳答案
对此有很多错误信息,但真正的原因是:
典型的服务器可能会处理 200 个连接。它将为每个需要写入或读取数据的连接提供服务,然后需要等待,直到有更多工作要做。在等待期间,如果在这 200 个连接中的任何一个上收到数据,则需要中断它。
使用select
,内核必须将进程添加到 200 个等待列表中,每个连接一个。为此,它需要一个“thunk”将进程附加到等待列表中。当进程最终唤醒时,需要将其从所有 200 个等待列表中删除,并且需要释放所有这些 thunk。
相比之下,对于epoll
,epoll
套接字本身有一个等待列表。该进程只需使用一个 thunk 就可以被放入一个等待列表中。当进程唤醒时,只需将其从一个等待列表中删除,并且只需释放一个 thunk。
需要明确的是,对于 epoll
,epoll
套接字本身必须附加到这 200 个连接中的每一个。但这对于每个连接都会在第一次被接受时完成一次。当它被移除时,对于每个连接,它都会被拆除一次。相比之下,每次调用阻塞的 select
都必须将进程添加到每个正在监视的套接字的每个等待队列中。
讽刺的是,对于select
,最大的成本来自于检查没有事件的套接字是否有任何事件。使用 epoll,无需检查没有事件的套接字,因为如果它们确实有事件,它们会在该事件发生时通知 epoll 套接字。从某种意义上说,每次调用 select
时,select
都会轮询每个套接字以查看是否有任何事件,而 epoll
会对其进行配置,以便套接字事件本身通知进程。
关于select - 为什么 epoll 比 select 快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17355593/