[muduo学习笔记]事件分发器(Channel、Poller)

此学习笔记参考施磊老师的muduo教学课程。
目的是搞懂 muduo 网络库的核心框架。EventLoop、channel 和 Poller 之间的关系


整体框架如下:
在这里插入图片描述

muduo是基于 Reactor 模式的网络库,他有三个核心组件支撑一个 reactor 实现持续的监听一组fd,并根据每个 fd 上发生的事件调用相应的处理函数。这三个组件分别是 Channel 类、Poll类以及EventLoop类。
EventLoop 是 Reactor 的核心,主要负责事件分发。在事件分发器中有两个重要部分,分别为 Poller 和 Channel。

1 Poller 抽象基类

说到事件循环,最常见的有 select、poll、epoll 等,在 muduo 中,选择使用抽象基类 Poller 来定义,在派生基类中实现 poll 和 epoll 。

// EventLoop.h 中的定义
std::unique_ptr<Poller> poller_;

// DefaultPoller.cc
#include <stdlib.h>
#include "Poller.h"
#include "EPollPoller.h"

Poller *Poller::newDefaultPoller(EventLoop *loop)
{
    // getenv 环境变量
    if (::getenv("MUDUO_USE_POLL"))
    {
        return nullptr; // 生成poll的实例,这里没有实现
    }
    else
    {
        return new EPollPoller(loop); // 生成epoll的实例
    }
}

在 EPollPoller 中的 epoll 实现,需要考虑 epoll 所感兴趣的事件 event, 在 event 中绑定了一个 sockfd 以及它所感兴趣的事件,这些都封装在 Channel 中。

// channel.h 中的成员变量
const int fd_;                   // fd,Poller监听的对象
int events_;                     // 注册fd感兴趣的事件
int revents_;                    // Poller返回的具体发生的事件

2 Channel

它是 EventLoop 的另一个重要部分,Channel理解为通道,它封装了sockfd 和其感兴趣的 event 如 EPOLLIN、EPOLLOUT 事件,还绑定了 poller 返回的具体事件

// EventLoop.h 中的定义
using ChannelList  = std::vector<Channel*>;

所有的成员函数都在这里:
channel中的成员函数

这里只说明一些:
在 Channel 中使用智能指针,是防止我们手动调用了 removeChannel后,还在使用已经被删除的 Channel。它完成跨线程状态的监听。weak_ptr 和 shared_ptr 配合使用,可以解决 shared_ptr 的值循环引用的问题,在多线程中使用 weak_ptr来监听它所观察的资源的状态,使用时尝试提升为 shared_ptr ,提升成功,访问,提升失败,就不访问,说明它所观察的资源已经被释放。

std::weak_ptr<void> tie_;        // 防止手动 remove Channel后仍在执行回调操作。
bool tied_;

智能指针的学习参考:
C++基础——智能指针 shared_ptr 和 weak_ptr 的使用
C++智能指针 shared_ptr,unique_ptr和weak_ptr

当 poller 中有监听事件,channel 就会调用相应的回调。

// 设置fd相应的事件状态 相当于 epoll_ctl add delete
    /*
        const int Channel::kNoneEvent = 0;
        const int Channel::kReadEvent = EPOLLIN | EPOLLPRI;
        const int Channel::kWriteEvent = EPOLLOUT;
    */
    void enableReading()  { events_ |= kReadEvent;   update(); }     // 让 fd 对读事件感兴趣
    void disableReading() { events_ &= ~kReadEvent;  update(); }     // ~:使得read的那一位是0,,再&=上其他位,把相应的位置成0,去掉,
    void enableWriting()  { events_ |= kWriteEvent;  update(); }
    void disableWriting() { events_ &= ~kWriteEvent; update(); }
    void disableAll()     { events_  = kNoneEvent;   update(); }

3 模块的包含

前面说过,EventLoop 是 Reactor 的核心,主要负责事件分发。在事件分发器中有两个重要部分,分别为 Poller 和 Channel。
根据高性能服务器模型:one loop per thread,可以得出一个线程中有一个EventLoop ,一个EventLoop 中有一个poller,一个 poller 上可以监听很多 channel。
所一个channel有一个 EventLoop,一个 EventLoop 有多个channel。

muduo模块梳理参考:

重写muduo网络库:各模块交互流程梳理总结

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值