学习muduo库(11)之eventpoll类

预备知识:

poll:

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

参数:

fds:这是一个结构体数组指针。nfds:是这个数组的大小。timeout:表示poll的阻塞时间。

typedef struct pollfd {
        int fd;           /* 需要被检测或选择的文件描述符*/
        short events;     /* 对文件描述符fd上感兴趣的事件,用户设置这个值 */
        short revents;    /* 文件描述符fd上当前实际发生的事件,poll函数返回这个值*/
} pollfd_t;

poll函数的工作过程:

poll函数会遍历整个结构体数组,检查每一个结构体中的文件描述符是否发生感兴趣的事件,如果文件描述发生事件,会将发生的事件返回到renents中。经过一次遍历,如果有事件发生,将会返回发生事件的个数,如果没有事件发生继续遍历,直至有事件发生或者阻塞时间超过timeout规定的时间。poll超时,将会返回0

epoll:

int epoll_create(int size);

 int epoll_create(int size);此函数会创建一个内核事件表,size是这个内核事件表的大小,返回值是这个内核事件的文件描述符。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);这个函数的作用就是将某个文件描述符,注册到上面提到的内核事件表,或者从内核事件表中修改此文件描述符,或删除此文件描述符。

参数含义:

1. epfd: 要操作的内核事件表的文件描述符,即 epoll_create 的返回值
2. op:指定操作类型,操作类型有三种:
    -> EPOLL_CTL_ADD:往内核事件表中注册指定fd 相关的事件
    -> EPOLL_CTL_MOD:修改指定 fd 上的注册事件
    -> EPOLL_CTL_DEL:删除指定 fd 的注册事件
3. fd:所要操作的文件描述符,也就是要内核事件表中监听的 fd
4. event:指定所要监听的事件类型,epoll_event 结构指针类型。

struct epoll_even的结构如下:

typedef union epoll_data {
    void *ptr;
    int fd;
    __uint32_t u32;
    __uint64_t u64;
 } epoll_data_t;

 struct epoll_event {
    __uint32_t events; /* Epoll events */
    epoll_data_t data; /* User data variable */
};

其中 events 成员描述事件类型,可以是以下几种类型宏的集合:

EPOLLIN:表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

成功返回0 , 否则返回-1

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

参数
(1) epfd
要操作的内核事件表的文件描述符,即 epoll_create 的返回值

(2) events
内核事件表中得到的检测事件集合

(3) maxevents & timeout
maxevents 告诉内核 events 的最大 size,timeout 指定超时时间
 

epoll的工作过程:

通过上面的介绍可知,epfd是我们的内核事件表,我们关心的文件描述符都在这个表里,与poll不同,epoll并不会遍历这个表,而是,这个表里一旦有事件发生,就会调用回调函数,将对应的struct event写入events(这是一个空的数组)。如果没有事件发生,继续阻塞,直至超过timeout的时间。

UML:

解释:

这是muduo库中最主要的一个类。Poller是一个抽象类,PollPoller和EPollPoller是两个具体类,分别是用Linux提供的poll和epoll实现的。

每一个eventloop中对应着一个poller来处理事件。eventloop中有一个channellist这里面包含了很多channel,每一个channel对应着一个需要处理的事件。

工作流程:

 第一步:新建一个channel,创建channel的时候,需要指定channel所属的eventloop对象,以及所关注事件的文件描述符。

第二步:channel调用自己的updata()方法,这个方法将会调用,其所属的eventloop的updatachannel()方法。

第三步:eventloop的updatachannel()方法将会调用,poller中的updatachannel()方法。

第四步:poller中的updatachannel()将会将所关注的事件添加到poll或者epoll中。

第一步:eventloop的loop()方法会产生一个循环,这个循环中会不断处理关注的事件。

第二步:poller的poll()方法会去观测所有的关注事件,并返回需要处理的事件序列activechannels

第三部:遍历需要处理的事件序列activechannels,处理每一个需要处理的事件。

第四步:继续循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值