IO多路复用
一、概念
I/O多路复用,I/O指的是网络I/O,多路值多个TCP连接(socket或者channel),复用指复用一个或者几个线程;
简单来说:就是使用一个或几个线程处理多个TCP连接
最大的优势是减少系统的开销,不必创建过多的进程/线程,也不必维护这些进程/线程。
二、select
基本原理:
监视文件三类描述符:writefds,readfds和exceptfds。
调用select函数会堵塞住,等有数据 可读、可写、出异常或者超时就会返回
select函数正常返回后,通过遍历fdset整个数组才能发现哪些句柄发生了事件,来找到就绪的描述符fd,然后进行对应的IO操作。
几乎在所有的平台支持,跨平台特性好。
缺点:
select采用轮询的方式扫描文件描述符,全部扫描,随着文件描述符FD数量增多而性能下降
每次调用select()需要把fd集合从用户态拷贝到内核态,并进行遍历(消息传递都是从内核到用户空间)
最大的缺陷就是单个进程打开的FD有限制,默认是1024(可修改宏定义,但是效率仍然慢)
三、poll
select和poll系统调用是一样的,处理多个描述符也是使用轮询的方式,根据描述符的状态进行处理一样需要把fd集合从用户态拷贝到内存态,并进行遍历。
最大的区别:poll没有最大文件描述符限制(使用链表方式存储的fd)
四、epoll
在2.6内核中提出,对比select和poll,epoll更加灵活,没有描述符限制,用户态拷贝到内核态只需要一次使用通知事件,通过epoll_etl注册fd,一旦fd就绪,内核就会采用callback的回调机制来激活对应的fd。
优点:
没有fd的限制,所支持的fd上限是操作系统的最大文件句柄数,1G内存大概支持10万句柄。
效率提高,使用回调通知,而不是使用轮询的方式,不会随着fd数目的增加而效率下降。
通过callback机制通知,内核和用户空间mmap同一块内存实现
缺点:
编程模型比select/poll复杂
linux内核函数实现:
epoll_create() 在linux内核申请一个文件系统,B+树结构,返回这个epoll对象,是一个fd。
epoll_etl() 操作epoll对象,在这个对象里面添加删除修改对应的链接fd,绑定一个callback函数
epoll_wait() 判断并完成对应的IO操作
