1.epoll_create()函数

    函数原型:int epoll_create(int size);

    功能:创建一个epoll对象,返回该对象的文件描述符,这个描述符就代表这个epoll对象。

    这个epoll对象最终要用close()释放,因为文件描述符总是关闭的。

    size:保证其值大于0

    原理:

    (1)struct eventpoll *ep = (struct eventpoll*)calloc(1, sizeof(struct eventpoll));

    (2)rbr结构体成员:代表创建一个红黑树的根节点[刚开始指向空]

        红黑树,用来保存    键[数字]/值[结构],能够快速的通过key,把整个value取出

    (3)rdlist结构成员:代表 一个双向链表的表头指针

         双向链表:从头访问/遍历每个原型。

    总结:创建了一个初始化eventpoll结构对象,被系统保存,rbr成员被初始化成一个棵红黑树的根节点,rdlist成员被初始化成指向一个双向链表的根。

epoll原理分析epoll原理分析

2.epoll_ctl()函数

    函数原型:int epoll_ctl(int efpd, int op, int sockid, struct epoll_event *event);

    功能:把一个socket以及这个socket相关的事件添加到这个epoll对象描述符中区,目的是通过这个epoll对象来监视这个socket[客户端的TCP连接]当有数据来往时,系统会通知我们。

    epfd:epoll_create()返回的epoll对象。

    op:动作添加/删除/修改,对应数字1,2,3,EPOLL_CTL_ADD,EPOLL_CTL_DEL,EPOLL_CTL_MOD

        添加事件:往红黑树中添加一个节点,每个客户端连入服务器后,服务器都会产生一个socket,每个socket的值都不会重复,所以这个socket就是红黑树的key。

        EPOLL_CTL_NOD修改事件:你用了EPOLL_CTL_ADD把这个节点添加到红黑树上之后,才存在修改

        EPOLL_CTL_DEL删除事件:把该节点从红黑树上移除,这会导致这个socket上无法收到任何系统通知事件

    sockid:表示客户端连接,accept()函数的返回值,这就是红黑树的key。

    event:事件信息,这里包括的是一些事件信息:EPOLL_CTL_ADD和EPOLL_CTL_MOD都要用到这个event参数里边的事件信息。

    原理:

        (1)epi = (struct epitem*)calloc(1, sizeof(struct epitem)); //创建一个红黑树节点

        (2)epi = RB_INSERT(_epoll_rb_socket, &ep->rbr, epi); //红黑树中添加一个节点【EPOLL_CTL_ADD】

            epitem.rbn代表三个指针,左子树,右子树以及父节点

        (3)epi = RB_REMOVE(_epoll_rb_socket, &ep->rbr, epi); //从红黑树中移除一个节点【EPOLL_CTL_DEL】

        (4)struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); //找到节点后修改该节点的内容  【EPOLL_CTL_MOD】

            if (epi) {

                epi->event.events = event->events;

                epi->event.events |= EPOLLERR | EPOLLHUP;

            } else {

                errno = -ENOENT;

                return -1;

            }

    总结:EPOLL_CTL_ADD添加红黑树节点,EPOLL_CTL_DEL从移除红黑树节点并释放内存,EPOLL_CTL_MOD修改红黑树中的数据(epitem即可作为红黑树的节点也可作为双向链表的节点)

epoll原理分析

3.epoll_wait()函数

函数原型int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

功能:阻塞一段时间并等待事件发生,返回事件集合,也就是获取内核的实践通知。===》遍历epoll_create()时创建的双向链表,把这个双向链表中的节点数据拷贝一份,拷贝完成的就从双向链表中移除。因为双向链表中记录的是有事件发生的socket[TCP连接]

epfd:epoll_create()返回的epoll对象

events:是内存,也是数组,长度为maxevents,表示此次epoll_wait()调用可以接收到的maxevents个已经就续的读写事件,返回的是实际发生实际的TCP连接。

timeout:阻塞等待的时长。

4.内核向双向链表中添加节点

    有以下四种情况

    1.客户端完成三次握手:服务器调用accept()

    2.客户端关闭连接:服务器需要调用close()

    3.客户端发送数据:服务器需要调用read()/recv()接收

    4.当可以发送数据:服务器需要调用send()/write()

    5.其它

 

 

 

 

 

 

 

 

 

 

 

 

相关文章: