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;

原理:
在这里插入图片描述

  1. struct event* ep = (struct eventpoll*)calloc(1,sizeof(struct eventpoll));
  2. rbr结构成员:代表一个红黑树的根节点(刚开始指向空),把ebe理解成红黑树的根节点的指针;红黑树用来保存键值对,键【数字】值【结构】,能够快速的通过key取出值。
  3. rdlist结构成员为双向链表的表头指针;从头访问每个元素很快
    在这里插入图片描述

1.2 epoll_ctl()函数

int epoll_ctr(int efpd,int op,int sockid,struct epoll_event* event);

功能:

  1. 把一个socket以及这个socket相关的事件添加到这个epoll对象描述符中去,目的就是通过这个epoll对象来监视这个socket【客户端tcp连接】上数据来往信号,当有数据来往时,系统会通知我们;
  2. 把感兴趣的事件通过epoll_ctr()添加到系统,当这个事件来的时候,系统会通知我们;
  3. efpd: epoll_create()返回的epoll对象描述符
  4. op:动作:添加、删除、修改,对应的数字为1 2 3,EPOLL_CTL_ADD,EPOLL_CTL_DEL,EPOLL_CTL_MOD
  5. EPOLL_CTL_ADD添加事件:等同于你往红黑树添加一个节点;每个客户端连入服务器后,服务器都会产生一个对应的socjet值,不重复,所以这个socket就是红黑树中的key,把这个结点添加到红黑树上去!EPOLL_CTL_MOD:修改事件,EPOLL_CTL_DEL:从红黑树中把这个结点干掉!会导致这个socket【这个tcp连接】上无法收到任何系统通知事件!
  6. sockid:表示客户端连接,也就是accept();这个就是红黑树里的key;
  7. 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中的东西)

面试常问:

  1. 红黑树结点是epoll_ctl()函数【EPOLL_CTL_ADD】往里面增加结点的!
  2. 红黑树结点是epoll_ctl()函数【EPOLL_CTL_DEL】删除的!(把结点干掉)
  3. 【EPOLL_CTL_MOD】删除结点内容(结点中的event)

1.3 epoll_wait()函数

当事件发生,如何拿到操作系统的通知?
格式:

int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);

功能:
阻塞一小段时间并等待事件发生,返回事件集合,也就是获取内核的事件通知;说白了就是遍历这个双向链表,把这个双向链表里边的结点数据拷贝出去,拷贝完毕的就从双向链表里面移除;双向链表里存储的是所有 有数据/有事件的socket(tcp连接)。

参数:

  1. epfd:是epoll_create()返回的epoll对象描述符
  2. events:是内存,也是数组,长度是maxevents,表示此次epoll_wait()调用可以收集到的maxevents个事件/socket连接(已经准备好的读写事件)!说白了,就是返回的实际发生事件的tcp连接的数目!
  3. timeout:阻塞等待的时长

总结:
epitem结构设计的高明之处:既能够作为红黑树中的结点,也能够作为双向链表的结点!(rdlink)
在这里插入图片描述

内核向双向链表增加结点

一般有四种情况,会使操作系统把结点插入到双向链表中

  1. 客户端完成三次握手了服务器要accept();
  2. 当客户端关闭连接,服务器也要调用close()关闭
  3. 客户端发数据来;服务器要调用read recv函数来收数据
  4. 当可以发送数据时,服务器可以调用send write函数。

epoll_event_callback():
当客户端发生上述情况后,操作系统会调用这个函数,用来往双向链表中增加一个结点!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐