Epoll技术深入学习
一, Epoll概述
- epoll就是一种典型的IO多路复用,支持高并发,号称一百万
- 传统select, poll 在并发量1000-2000的时候性能明显下降
- epoll是Linux内核2.6引入的技术。(kqueue类似,在其他系统中
- 十万个连接同一时刻,只有几十上百个客户端给你发数据,epoll只处理这几十上百个连接
- 很多服务器每个进程,或每个线程对应一个连接。涉及进程切换损坏
- epoll事件驱动机制,在单独进程或线程单独运行。收集处理技术
二,Epoll的工作原理(三个函数)
- epoll_create()
- 原型:int epoll_create(int size)
- 创建一个epoll对象,返回对象描述符
- 最终要调用close(), 因为文件描述符 总是关闭的
- 原理:
- 创建一个eventpoll的结构对象。
- rbr是一颗红黑树
- rdlist结构代表一个双向链表表头指针,从头访问遍历每个元素
- 创建一个eventpoll的结构对象。
- epoll_ctl()
- 原型:int epoll_ctl(int efpd, int op, int sockid, struct epoll_event &event);
- 功能:把感兴趣的事件添加到系统中去
- efpd: 就是epoll_create返回的文件描述符
- op: 动作,添加/删除/修改,对于1,2,3,当时系统有宏EPOLL_CTL_ADD,EPOLL_CTL_DEL,EPOLL_CTL_MOD
- add 就是往红黑树上加结点。每次tcp连接获得一个socket,即红黑树的key
- mod修改,
- del删除,从红黑树把结点干掉,TCP连接上无法收到任何通知了
- sockid: 一个客户端一个socket,就是accpet(); 就是红黑树的key
- event:事件信息。
- 原理:
- 其实就是红黑树上的维护过程。
- EPOLL_CTL_ADD: 往红黑树中增加结点
- EPOLL_CTL_DEL: 往红黑树中删除结点
- EPOLL_CTL_MOD: 往红黑树中修改结点
- epoll_wait
- 原型:int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
- 阻塞一小段时间并等待事件发生,返回事件的集合。也就是获取内核通知事件
- 把双向链表中移除(双向链表记录的是所有有数据的TCP连接)
- efpd: 就是epoll_create返回的文件描述符
- events: 数组,长度是maxevents。标示这一次epoll_wait收集到的事件数目。从双向链表中取节点
-
- 一般有四种情况,操作系统会回调把事件插入到双向链表中
- 完成三次握手,accept()。
- 客户端关闭连接,close()。
- 客户端发送数据来的时候。
- 当可以发送数据的时候,服务器调用send(),write()。
- 其他。。。
- 一般有四种情况,操作系统会回调把事件插入到双向链表中
三,实际使用
四,LT和ET
- LT(level trigger) 水平触发,低速效率差, 默认模式
- ET(edge trigger) 边沿触发,高速模式(效率好)
- 现状:
- 所有的监听套接字都是水平触发
- 所有的接入进来的用户套接字都是边缘触发
本质区别:
- 水平触发: 来一个事件,如果你不处理它,那么这个事件就会一直触发;
- 边缘触发: 只对非阻塞socket有用. 来一个事件,内核只通知一次.不管你是否处理
- 代价: 编码的难度加大, 接到通知后要保证处理问题.