epoll介绍及原理详解
Posted 为了财务自由!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了epoll介绍及原理详解相关的知识,希望对你有一定的参考价值。
1. epoll原理与函数介绍
四个重要的函数
epoll_create();
epoll_ctl();
epoll_wait();
epoll_event_callback();
1.1 epoll_create()函数
int epoll_create(int size);
创建一个epoll对象,返回该对象的描述符(文件描述符),这个描述符就代表这个epoll对象,后续会用到;
这个epoll对象最终是要close()的,因为文件描述符始终是要关闭的!size>0;
原理:
- struct event* ep = (struct eventpoll*)calloc(1,sizeof(struct eventpoll));
- rbr结构成员:代表一个红黑树的根节点(刚开始指向空),把ebe理解成红黑树的根节点的指针;红黑树用来保存键值对,键【数字】值【结构】,能够快速的通过key取出值。
- rdlist结构成员为双向链表的表头指针;从头访问每个元素很快
1.2 epoll_ctl()函数
int epoll_ctr(int efpd,int op,int sockid,struct epoll_event* event);
功能:
- 把一个socket以及这个socket相关的事件添加到这个epoll对象描述符中去,目的就是通过这个epoll对象来监视这个socket【客户端tcp连接】上数据来往信号,当有数据来往时,系统会通知我们;
- 把感兴趣的事件通过epoll_ctr()添加到系统,当这个事件来的时候,系统会通知我们;
- efpd: epoll_create()返回的epoll对象描述符
- op:动作:添加、删除、修改,对应的数字为1 2 3,EPOLL_CTL_ADD,EPOLL_CTL_DEL,EPOLL_CTL_MOD
- EPOLL_CTL_ADD添加事件:等同于你往红黑树添加一个节点;每个客户端连入服务器后,服务器都会产生一个对应的socjet值,不重复,所以这个socket就是红黑树中的key,把这个结点添加到红黑树上去!EPOLL_CTL_MOD:修改事件,EPOLL_CTL_DEL:从红黑树中把这个结点干掉!会导致这个socket【这个tcp连接】上无法收到任何系统通知事件!
- sockid:表示客户端连接,也就是accept();这个就是红黑树里的key;
- event:事件信息。包括的是一些事件信息:EPOLL_CTL_ADD、EPOLL_CTL_MOD都要用里边的事件信息;
原理:
红黑树结点:
a. 生成内存对象
epi = (struct epitem*)calloc(1,sizeof(struct epitem));
b.
epi=RB_INSERT(_epoll_rb_socket,&ep->rbr,epi);
【EPOLL_CTL_ADD】增加结点到红黑树中
epitem.rbn,代表三个指针,分别指向红黑树的左子树,右子树,父亲;
epi=RB_REMOVE(_epoll_rb_socket,&ep->rbr,epi);
【EPOLL_CTL_DEL】从红黑树中把结点删除
EPOLL_CTL_MOD,找到红黑树结点,修改这个结点的内容!(修改event中的东西)
面试常问:
- 红黑树结点是epoll_ctl()函数【EPOLL_CTL_ADD】往里面增加结点的!
- 红黑树结点是epoll_ctl()函数【EPOLL_CTL_DEL】删除的!(把结点干掉)
- 【EPOLL_CTL_MOD】删除结点内容(结点中的event)
1.3 epoll_wait()函数
当事件发生,如何拿到操作系统的通知?
格式:
int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);
功能:
阻塞一小段时间并等待事件发生,返回事件集合,也就是获取内核的事件通知;说白了就是遍历这个双向链表,把这个双向链表里边的结点数据拷贝出去,拷贝完毕的就从双向链表里面移除;双向链表里存储的是所有 有数据/有事件的socket(tcp连接)。
参数:
- epfd:是epoll_create()返回的epoll对象描述符
- events:是内存,也是数组,长度是maxevents,表示此次epoll_wait()调用可以收集到的maxevents个事件/socket连接(已经准备好的读写事件)!说白了,就是返回的实际发生事件的tcp连接的数目!
- timeout:阻塞等待的时长
总结:
epitem结构设计的高明之处:既能够作为红黑树中的结点,也能够作为双向链表的结点!(rdlink)
内核向双向链表增加结点
一般有四种情况,会使操作系统把结点插入到双向链表中
- 客户端完成三次握手了服务器要accept();
- 当客户端关闭连接,服务器也要调用close()关闭
- 客户端发数据来;服务器要调用read recv函数来收数据
- 当可以发送数据时,服务器可以调用send write函数。
epoll_event_callback():
当客户端发生上述情况后,操作系统会调用这个函数,用来往双向链表中增加一个结点!
以上是关于epoll介绍及原理详解的主要内容,如果未能解决你的问题,请参考以下文章