- select: 每个连接对应一个描述符(socket),循环处理各个连接,先查下它的状态,ready了就进行处理,不ready就不进行处理。但是缺点很多:
每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
select支持的文件描述符数量太小了,默认是1024
- poll: 本质上和select没有区别,但是由于它是基于链表来存储的,没有最大连接数的限制。缺点是:
大量的的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。
poll的特点是「水平触发(只要有数据可以读,不管怎样都会通知)」,如果报告后没有被处理,那么下次poll时会再次报告它。
- epoll: 它使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。epoll支持水平触发和边缘触发,最大的特点在于「边缘触发」,它只告诉进程哪些刚刚变为就绪态,并且只会通知一次。使用epoll的优点很多:
没有最大并发连接的限制,能打开的fd的上限远大于1024(1G的内存上能监听约10万个端口)
效率提升,不是轮询的方式,不会随着fd数目的增加效率下降
内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销