HarmonyOS--事件驱动模型Reactor(事件调度、计时器、事件处理器)
引言
Reactor模式是处理并发I/O比较常见的一种模式,中心思想是将所有的事件(handler)的具体I/O事件注册到一个多路复用器(epoll)上,同时我们的主线程都阻塞在多路复用器(epoll)上,同时我们的事件有I/O事件触发(文件描述符可读、可写、错误、关闭),多路复用器(epoll)上会返回并将事件注册的相应I/O事件分发到关联的处理器(event_handler)中。HarmonyOS针对Reactor模式的开发分成了4个模块,分别为多路复用器(event_demultiplexer),事件处理器(event_handler),调度器(event_reactor),计时器(timer_event_handler)。
多路复用器
类名:event_demultiplexer
功能:阻塞等待被监听的事件文件描述符集合,采用epoll实现I/O复用,用来等待批量的fd。
工作流程图:
要点
①多路复用器是采用epoll实现的多路复用
②epoll底层采用了红黑树,提高了增删改查的效率
③采用epoll_create1(EPOLL_CLOEXEC)创建epoll,可以避免掉fork子进程时,开发者忘记关闭父进程打开的fd的情况
常用API
①uint32_t StartUp(),启动事件多路复用器(epoll)
//启动事件多路分离器 uint32_t EventDemultiplexer::StartUp() { //判断epoll是否创建成功 if (epollFd_ < 0) {//未创建成功则,重新创建 epollFd_ = epoll_create1(EPOLL_CLOEXEC); if (epollFd_ < 0) {//再次创建失败则返回TIMER_ERR_BADF UTILS_LOGE("epoll_create1 failed.");//记录失败原因到日志中 return TIMER_ERR_BADF; } } return TIMER_ERR_OK;//启动成功,返回TIMER_ERR_OK }
②void CleanUp(),关闭事件多路复用器(epoll)
③void Polling(int timeout),监听epoll,最多阻塞timeout时间,获取到被触发的events链表,并根据触发的具体事件,通知对应的事件处理器去处理。
/* 函数功能:监听epoll,最多阻塞timeout时间,获取到被触发的event链表,并根据触发的具体事件,通知对应的EventHandler去处理。 函数参数:timeout,本函数陷入阻塞的最大时间 函数返回值:void */ void Polling(int timeout);
④uint32_t UpdateEventHandler(EventHandler* handler),更新多路复用器中存放的事件处理器
/* 函数功能:更新EventDemultiplexer事件多路分离器中存放的事件eventHandlers_的可操作事件处理器 函数参数:handler,事件处理器 函数返回值:uint32_t,返回操作结果的状态码 */ uint32_t UpdateEventHandler(EventHandler* handler);
⑤uint32_t RemoveEventHandler(EventHandler* handler),移除多路复用器中存放的事件处理器
/* 函数功能:移除传入的事件句柄EventHandler事件处理器 函数参数:handler,事件处理器 函数返回值:uint32_t,返回操作结果的状态码 */ uint32_t RemoveEventHandler(EventHandler* handler);
调度器
类名:event_reactor
功能:用于管理事件处理器EventHandler(包括定时器),其主要功能有注册、删除,更新EventHandler,将EventHandler注册为响应事件fd建立关系(回调函数),是多路复用器的入口,通过RunLoop()调用多路复用器的epoll方法阻塞等待事件的发生,根据触发的具体事件,分发给指定的事件处理器处理,即存放的EventHandler中的HandleEvents()方法。
单模块架构图:
主要API
void UpdateEventHandler(EventHandler* handler),从reactor中更新(添加)事件处理器。
uint32_t ScheduleTimer(),添加一个调度器的定时器,指定时间间隔,返回一个可读事件。
void CancelTimer(int timerFd),删除一个定时器
事件处理器
类名:EventHandler
功能:定义了I/O事件中读、写、错误、关闭操作的回调函数,需要开发者自己传入对应可操作事件的回调函数。
框架图:
Reactor总体架构
- handle:即操作系统中的句柄fd,可以是文件、Socket,定时器Timer,将这个句柄注册到多路复用器中,监听fd上发生的读、写、错误、关闭等事件。
- 多路复用器:HarmonyOS采用的epoll实现的多路复用,阻塞等待被监听的事件文件描述符集合,用来等待批量的fd,直到又事件触发。
- 调度器:用于管理事件处理器EventHandler(包括定时器),其主要功能有注册、删除,更新EventHandler,将EventHandler注册为响应事件fd建立关系(回调函数),是多路复用器的入口,通过RunLoop()调用多路复用器的epoll方法阻塞等待事件的发生,根据触发的具体事件,分发给指定的事件处理器处理,即存放的EventHandler中的HandleEvents()方法。
- 事件处理器:定义了I/O事件中读、写、错误、关闭操作的回调函数,需要开发者自己传入对应可操作事件的回调函数。
- 定时器事件处理器:提供对调度器起一个更加精确的时间控制器,通过将定时器fd写入epoll中,设置一段时间后,触发可读事件,可以做到与事件处理器意义配对的效果。
Reactor模式之间交互图:
流程分析:
1、初始化调度器EventReactor和多路复用器event_demultiplexer,并将多路复用器event_demultiplexer存放在调度器中
2、注册事件处理器EventHandler到多路复用器event_demultiplexer中,采用map存放,从而建立了handle与事件处理器EventHandler的映射。
3、注册定时器TimerEventHandler存放在多路复用器event_demultiplexer中,采用map存放,且在调度器中存放所有的定时器。
4、调用调度器EventReactor的RunLoop()轮询多路复用器event_demultiplexer中的epoll_wait(),使其阻塞等待event事件发生。
5、当定时器或者某些handle的触发事件触发后,引起epoll返回,多路复用器event_demultiplexer根据存放的map映射,找到相应的事件处理器EventHandler,并回调事件处理器的HandleEvents