关于io多路复用中,select、poll和epoll的相关知识。
共同点
均用于实现io多路复用(一个线程同时管理和检测多个io是否就绪)
且都是同步io。即所提供的接口 返回时是否完成了它的职责:
如select,就是把就绪的io全部提取出来,在它返回的同时,也完成了提取操作,故而是同步io
具体实现
select
只提供一个接口,通常需要传入读事件readfds和写事件writefds,返回异常事件exceptfds
1 |
|
poll
只提供一个接口,在select中的三个事件,在poll中用events来表示。
poll返回时,通常读取返回事件revents
1 |
|
epoll
提供三个接口,epoll_create()、epoll_ctl()、epoll_wait()
1 |
|
epoll_create()
调用epoll_create时,会创建epoll的实例,也就是epoll fd。
在内核中,会创建两个结构,分别是 红黑树 和 就绪队列。
epoll_ctl()
主要操作红黑树,进行 增 删 改 操作。
其中输入参数 int op
,表示三种操作 EPOLL_CTL_ADD、EPOLL_CTL_DEL、EPOLL_CTL_MOD
其中输入参数 int fd
,表示需要去具体操作的fd
epoll_wait()
将就绪队列的数据 拷贝到用户态。
其中输入参数 struct epoll_event *events
,表示从内核中的就绪队列中的数据 拷贝装载下来的容器
其中输入参数 int maxevents
,表示上面转载数组最大的大小
何为io读写事件
- accept(listenfd,&addr,&size); 读事件
- connect(connfd,&addr,&size); 写事件
- read(fd, buf, sz); 读事件
- write(fd, buf,sz); 写事件
select、poll和epoll的区别
接口上
select、poll只有一个接口;
epoll有三个接口,事实上epoll用两个接口实现上述一个接口的功能。
传参及返回上
select 需要传递可读,可写,异常三个集合,select返回后仍需遍历取出就绪事件
poll 只需要传递一个集合,poll返回后仍需遍历取出就绪事件
epoll 通过epoll_ctl只需添加一次,epoll_wait取出就绪的事件
底层实现上
select、poll通过轮询;select是数组,poll是链表;
epoll通过回调机制,将就绪io从红黑树拷贝到就绪队列;
管理fd数量上
select 有限制 FD_SETSIZE
poll 和 epoll没有限制
出发机制上
select、poll只有水平触发
epoll有水平触发和边沿触发
效率上
少量fd,都比较活跃的情况下,select\poll性能更高
大量fd,小部分活跃的情况下,epoll性能更高