彻底理解 IO 多路复用实现机制( 五 )


彻底理解 IO 多路复用实现机制文章插图
从上面的讲解可知:通过红黑树和双链表数据结构 , 并结合回调机制 , 造就了epoll的高效 。讲解完了Epoll的机理 , 我们便能很容易掌握epoll的用法了 。 一句话描述就是:三步曲 。

  • 第一步:epoll_create()系统调用 。 此调用返回一个句柄 , 之后所有的使用都依靠这个句柄来标识 。
  • 第二步:epoll_ctl()系统调用 。 通过此调用向epoll对象中添加、删除、修改感兴趣的事件 , 返回0标识成功 , 返回-1表示失败 。
  • 第三部:epoll_wait()系统调用 。 通过此调用收集收集在epoll监控中已经发生的事件 。
epoll使用示例int main(int argc, char* argv[]){/** 在这里进行一些初始化的操作 ,* 比如初始化数据和socket等 。*/// 内核中创建ep对象epfd=epoll_create(256);// 需要监听的socket放到ep中epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,while(1) {// 阻塞获取nfds = epoll_wait(epfd,events,20,0);for(i=0;iepoll的优点
  • 没有最大并发连接的限制 , 能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口);
  • 效率提升 , 不是轮询的方式 , 不会随着FD数目的增加效率下降 。 只有活跃可用的FD才会调用callback函数;即Epoll最大的优点就在于它只管你“活跃”的连接 , 而跟连接总数无关 , 因此在实际的网络环境中 , Epoll的效率就会远远高于select和poll;
  • 内存拷贝 , 利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销 。
epoll缺点
  • epoll只能工作在 linux 下
epoll LT 与 ET 模式的区别epoll 有 EPOLLLT 和 EPOLLET 两种触发模式 , LT 是默认的模式 , ET 是 “高速” 模式 。
  • LT 模式下 , 只要这个 fd 还有数据可读 , 每次 epoll_wait 都会返回它的事件 , 提醒用户程序去操作;
  • ET 模式下 , 它只会提示一次 , 直到下次再有数据流入之前都不会再提示了 , 无论 fd 中是否还有数据可读 。 所以在 ET 模式下 , read 一个 fd 的时候一定要把它的 buffer 读完 , 或者遇到 EAGIN 错误 。
epoll使用“事件”的就绪通知方式 , 通过epoll_ctl注册fd , 一旦该fd就绪 , 内核就会采用类似callback的回调机制来激活该fd , epoll_wait便可以收到通知 。
select/poll/epoll之间的区别select , poll , epoll都是IO多路复用的机制 。 I/O多路复用就通过一种机制 , 可以监视多个描述符 , 一旦某个描述符就绪(一般是读就绪或者写就绪) , 能够通知程序进行相应的读写操作 。 但select , poll , epoll本质上都是同步I/O , 因为他们都需要在读写事件就绪后自己负责进行读写 , 也就是说这个读写过程是阻塞的 , 而异步I/O则无需自己负责进行读写 , 异步I/O的实现会负责把数据从内核拷贝到用户空间 。
epoll跟select都能提供多路I/O复用的解决方案 。 在现在的Linux内核里有都能够支持 , 其中epoll是Linux所特有 , 而select则应该是POSIX所规定 , 一般操作系统均有实现
彻底理解 IO 多路复用实现机制文章插图
epoll是Linux目前大规模网络并发程序开发的首选模型 。 在绝大多数情况下性能远超select和poll 。 目前流行的高性能web服务器Nginx正式依赖于epoll提供的高效网络套接字轮询服务 。 但是 , 在并发连接不高的情况下 , 多线程+阻塞I/O方式可能性能更好 。


推荐阅读