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