介绍三者是 muduo 网络库多 Reactor 模型中事件驱动的核心组件遵循「EventLoop 统筹调度Poller 底层检测Channel 事件封装」的分工逻辑共同实现「IO 事件的检测 - 分发 - 处理」闭环且严格遵循one loop per thread原则一个线程仅一个 EventLoop。关系完整交互流程初始化注册Channel 封装 fd 后通过update()调用 EventLoop 的updateChannel()最终触发 Poller 的updateChannel()将 fd 及感兴趣的事件如 EPOLLIN/EPOLLOUT注册到 Pollerepoll_ctlPoller 用unordered_mapint, Channel*维护 fd 与 Channel 的映射确保事件触发时能快速找到对应 Channel。事件检测EventLoop 的loop()循环调用 Poller 的poll()方法底层 epoll_wait阻塞等待 fd 上的事件触发Poller 检测到活跃事件后将事件填充到对应 Channel 的revents_并把活跃 Channel 列表返回给 EventLoop。事件分发 处理EventLoop 遍历活跃 Channel 列表调用 Channel 的handleEvent()Channel 依据revents_内核触发的事件分情况执行读 / 写 / 关闭 / 错误回调如 EPOLLIN 触发readCallback_EPOLLHUP 触发closeCallback_唤醒的交互流程可参考Linux多线程服务端编程使用muduo C网络库 8.3节子线程subLoop所属线程阻塞在epoll_wait是 muduo 「one loop per thread Reactor 模型」的核心设计本质是让线程 “休眠” 以等待事件触发避免空轮询浪费 CPU同时保证事件到来时能及时响应。关于阻塞的理解muduo主从Reactor模式的理解回到EventLoop的初始化EventLoop::EventLoop() : looping_(false) , quit_(false) , callingPendingFunctors_(false) //标识是否正在执行「待处理回调队列」中的回调用于跨线程唤醒的条件判断 , threadId_(CurrentThread::tid()) // 记录当前EventLoop是被哪个线程id创建的 即标识了当前EventLoop的所属线程id , poller_(Poller::newDefaultPoller(this)) // 创建默认的IO复用对象 epollPoller , wakeupFd_(createEventfd()) // 线程间唤醒用的 eventfd 文件描述符 , wakeupChannel_(new Channel(this, wakeupFd_)) // 绑定wakeupFd_的Channel对象 用来监听wakeupFd_的事件 { LOG_DEBUG(EventLoop created %p in thread %d\n, this, threadId_); if (t_loopInThisThread) { LOG_FATAL(Another EventLoop %p exists in this thread %d\n, t_loopInThisThread, threadId_); } else { t_loopInThisThread this; } //将 EventLoop 的 handleRead 方法绑定到当前 EventLoop 对象this生成一个可调用的回调对象传给 Channel wakeupChannel_-setReadCallback( std::bind(EventLoop::handleRead, this)); //告诉 Channel 要监听 wakeupFd_ 的「读事件EPOLLIN」并最终通过 Pollerepoll/kqueue 等将该事件注册到内核。 wakeupChannel_-enableReading(); // 每一个EventLoop都将监听wakeupChannel_的EPOLL读事件了 /* 这两行代码就是把 “唤醒的信号通路” 搭好 setReadCallback指定 “读事件触发后该做什么”执行 handleRead 清空 wakeupFd_ 的数据 enableReading告诉 Pollerepoll“我要监听这个 wakeupFd_ 的读事件”最终通过 epoll_ctl 把事件注册到内核。 */ } //给每个 EventLoop 配置好专属的 “监听唤醒信号的通道wakeupChannel_”并指定信号触发后的处理逻辑为后续跨线程唤醒打下基础。 //然后除了wakeupChannel_之外的其他Channel也可以绑到EventLoop干其他活EventLoop就像管家不同Channel是不同的房间干不同的活EventLoop 就像一个 “事件管家” wakeupChannel 是它的 “闹钟”其他 Channel 是它的 “正式工作”