I/O复用的三种方法

select、poll、epoll这三组I/O复用系统调用都能同时监听多个文件描述符,他们都通过timeout参数指定要等待的时间。直到事件就绪时返回,返回值就是就绪的文件描述符的数量。

下面我们从事件集、最大支持文件描述符数量,工作模式和具体实现方面比较一下他们的异同:

1、事件集
select的参数没有将文件描述符和事件绑定,他仅仅是一个文件描述符的集合,所以select需要分别用三个参数来区分传入的可读,可写及异常事件,这不仅限制了select只能处理这三种事件,另外由于内核对fd_set集合的在线修改,所以下次再调用select之前还需要重置这3个文件描述符集合。
poll将文件描述符和事件都定义在pollfd结构体中,使得任何事件都能被统一处理,而且pollfd将监测事件和就绪事件分开了,保证events不被改变,因此pollfd不需要重置pllfd结构中的events成员。但是因为select和poll返回的都是整个事件集合,所以他们查找就绪事件的文件描述符的效率都是O(n)。
epoll在内核中维护了一个事件表,而且还提供一个函数epoll_ctl来向事件表中添加、删除、修改事件,所以它无须每次都重置事件。因为epoll返回的都是就绪事件,所以epoll查找就绪事件的文件描述符的时间复杂度都是O(1)。

2、最大支持的文件描述符数量
poll和epoll都能达到系统允许打开的文件描述符的最大值。
select允许监听的最大文件描述符数量通常有限制,虽然可以修改,但是不建议修改。

3、工作模式
select和poll都只能处在相对低效的LT模式,而epoll可以处于ET高效模式。

4、具体实现
select和poll采用的都是轮询的方式,每次都要扫描整个事件集合,才能找到就绪事件的文件描述符。而epoll采用的是callback(回调机制),只要内核检测到就绪事件,就触发回调机制,将就绪事件移到就绪队列中等待用户处理。
select、poll和epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,epoll是通过内核用于用户空间mmapp同一块内存实现的,所以epoll就减少了一些不必要的拷贝。

猜你喜欢

转载自blog.csdn.net/qq_39539470/article/details/80369954