一、select和poll的执行原理是一样的:
1、将当前进程的所有文件描述符,一次性的从用户态拷贝到内核态。
2、在内核态中快速的无差别的遍历每个fd,判断是否有数据到达。
3、将所有fd状态,从内核态拷贝到用户态,并返回已就绪的fd的个数。
4、在用户态遍历判断具体哪个fd已就绪,然后进行相应的事件处理。
二、select的不足:
1、文件描述符表为bitmap结构,且有长度为1024的限制。
2、fdset无法做到重用,每次循环必须重新建立。
3、频繁的用户态和内核态拷贝,性能开销较大。
4、需要对文件描述符表进行遍历,O(n)的轮询时间复杂度。
三、poll的解决的问题和不足
1、poll模型采用pollfd数据结构,解决了select的1024个文件描述符的限制。
2、但仍然存在频繁的用户态和内核态的拷贝,性能开销较大。
3、需要对文件描述符表进行遍历,O(n)的轮询时间复杂度。
四、epoll
1、在epoll_ctl()函数中,为每个文件描述符都指定了回调函数,基于回调函数把就绪时间放到就绪队列中,因此把时间复杂度从o(n)降到了O(1)。
2、只需要在调用epoll_ctl()时传递一次文件描述符,epoll_wait()不需要再次传递文件描述符。
3、epoll基于红黑树+双链表存储事件,没有最大连接数的限制。
五、使用场景
1、如果你正在编写一个需要处理大量并发连接或高并发的服务器应用程序并且你的应用程序运行在Linux上,那么应该使用epoll。
2、如果你的应用程序不需要处理大量并发连接,或者你的应用程序不是运行在Linux上,那么你可以考虑使用select或poll。但是,请注意select和poll在处理大量文件描述符时的性能问题。
3、在某些情况下,如果知道应用程序只会使用很少量的文件描述符,并且你不需要处理大量的并发连接,那么使用select 或poll 也是可以接受的。