重写Sylar基于协程的服务器(5、IO协程调度模块的设计)
重写Sylar基于协程的服务器(5、IO协程调度模块的设计)
重写Sylar基于协程的服务器系列:
重写Sylar基于协程的服务器(0、搭建开发环境以及项目框架 || 下载编译简化版Sylar)
重写Sylar基于协程的服务器(5、IO协程调度模块的设计)
重写Sylar基于协程的服务器(7、TcpServer & HttpServer的设计与实现)
简述
sylar的IOManager模块本质上就是一个事件池,主要负责向epoll中注册事件和回调。实现了Idle协程的回调,回调是一个阻塞在epoll_wait上的事件循环,将有IO事件发生的协程唤醒。
核心数据结构
将socketfd封装成一个结构体FdContext,对于fd上的读写事件封装成EventContext,提供的TrigleEvent函数,在fd有读写事件发生时,将相应读写事件的EventContext::m_fiber成员放到EventContext::m_scheduler调度器中,可以唤醒阻塞的协程。FdContext结构体定义如下。
struct FdContext { typedef Mutex MutexType; struct EventContext{ void reset(); Fiber::ptr m_fiber = nullptr; std::function<void(void)> m_cb = nullptr; //记录协程调度器,表示,当事件发生,fiber or callback应该使用哪个协程调度器调度。 Scheduler* m_scheduler = nullptr; }; // nolock void TrigleEvent(Event event); EventContext& getEventContext(Event event); void resetEventContext(Event event); EventContext read; //读事件Handle EventContext write; //写事件Handle Event m_events = NONE; //记录当前FdContext哪些事件有效 int m_fd = -1; MutexType m_mutex; };
IOManager成员变量
IOManager的成员变量中有一个类型为std::vector<FdContext*>的数组,以每个socketfd作为数组下标,每个fd都能对应一个FdContext。如下。
class IOManager: public Scheduler, public TimerManager{ /* ... */ private: std::vector<FdContext*> m_fdContexts; // fd -> FdContext(和muduo的channel类似) std::atomic<uint32_t> m_penddingEventCount = { 0 }; // epoll监听的事件数 int m_pipfd[2]; // 管道fd、也称ticklefd,也称wakefd(Muduo) int m_epollfd; MutexType m_mutex; // 全局锁 };
IO协程调度器的设计
IO协程调度模块继承自协程调度模块,重新实现了协程调度的idle函数、isStop函数、tickle函数(功能和Muduo中EventLoop的wakeup函数一样)等。因为IO协程调度器继承自协程调度器,所以,现约定以下出现的协程调度器也指IO协程调度器。
-
构造函数,创建一对个管道和一个epollfd,并将管道的读端注册到epollfd上,作用是:通知和唤醒阻塞在idle协程的epoll_wait函数上的线程,每次在向调度器任务队列中添加任务时,向管道的写端写入一个字符,以唤醒阻塞的线程,开始处理任务。在构造函数里面会自动启动协程调度器。
-
addEvent,向epollfd注册一个fd的读写事件,并记录到IOManager::m_fdContexts数组里面,等待事件的触发。
-
delEvent / cancelEvent, 向epollfd取消或删除一个fd的读写事件,并记录到IOManager::m_fdContexts数组里面。
-
Idle函数(即idle协程的回调函数),既然调度到了idle协程,说明调度器的任务队列里面没任务了,所以,idle函数首先会调用epoll_wait,带超时的阻塞线程一段时间,超时或者有事件发生时,会检查有无定时器超时,如果有定时器超时就会将超时回调函数放到任务队列中去调度,然后去检查有哪些fd发生了哪些事件,将相关的协程唤醒。
Idle函数伪代码如图:
Idle函数流程图:
下一章将介绍HOOK模块。
感兴趣的同学,可以阅读一下本文实现的源码:https://github.com/LunarStore/lunar
本章完结
posted on 2024-02-03 13:34 LunarCod 阅读(100) 评论(0) 编辑 收藏 举报 来源
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通