简介
select、poll、epoll都属于IO多路复用机制的函数实现,IO模型具体介绍查看之前文章
select
select函数通过遍历fdset,来找到就绪的描述符
缺点:
- 每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
- 同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
- select单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024
poll
和select函数一样,poll通过轮询pollfd来获取就绪的描述符
但是它没有最大连接数的限制,原因是它是基于链表来存储的,但另外两个缺点仍然存在
epoll
epoll可以理解为event poll,采用基于事件的就绪通知方式,只要遍历那些被内核IO事件异步唤醒而加入就绪链表的描述符就行了,解决了以上select存在的三个缺点
epoll在底层实现了自己的高速缓存区,并且建立了一个红黑树用于存放socket,另外维护了一个链表用来存放准备就绪的事件
- 执行epoll_ create时,创建了红黑树和就绪链表
- 执行epoll_ ctl时,如果增加socket句柄,则检查在红黑树中是否存在,存在立即返回,不存在则添加到树上,然后向内核注册回调函数,用于当中断事件来临时向准备就绪链表中插入数据
- 执行epoll_wait时立刻返回准备就绪链表里的数据即可。
epoll优点
- 支持一个进程打开大数目的socket描述符(FD)
- IO效率不随FD数目增加而线性下降
- 使用mmap加速内核与用户空间的消息传递。
网友评论