什么是I/O多路复用
I/O多路复用是通过一种机制可以监听多个描述符,一旦某个描述符就绪(读就绪或者写就绪)能够通知程序进行相应的操作。常见的几种I/O多路复用函数select、poll、epoll。
1. select
select监听三种文件描述符:
- readfds:指向一组等待可读性检查的套接口
- writefds:指向一组等待可写性检查的套接口
- exceptfds:指向一组等待错误检查的套接口
调用select函数后会阻塞,直到有文件描述符进入就绪状态,或者超时;这时候就可以遍历fdset来找到就绪的描述符。
优点:
跨平台
缺点:
- 单进程打开的FD有大小限制,由FD_SETSIZE设置,默认值为1024。(数组存储的)
- 扫描方式为轮询,效率低。
- 需要维护一个存放大量fd的数据结构,这样造成在用户空间和内核空间进行拷贝时开销很大。
2. poll
poll的存在主要是为了解决select的最大连接数的限制,采用了链表的方式进行存储。其他方面跟select几乎一样。
3. epoll
相对于select、poll来讲,epoll更加灵活,它没有大小限制。并且采用了共享一份内存的方式来管理过个文件描述符,这样只需要进行一次拷贝,用户空间和内核空间都能进行访问。
epoll支持两种触发模式
epoll支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就绪态,并且只会通知一次。还有一个特点是,epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知。
1.LT模式(level triggered)
当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。
2.ET模式(edge triggered)
当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。