技术开发 频道

Redis数据库:事件驱动库结构详解

  initServer函数调用aeCreateTimeEvent函数来添加一个计时事件到server.el的timeEventHead字段中。timeEventHead是一个指向计时事件的链表。redis.c文件中initServer函数调用aeCreateTimeEvent函数形式如下:

aeCreateTimeEvent(server.el /*eventLoop*/, 1 /*milliseconds*/, serverCron /*proc*/, NULL /*clientData*/, NULL /*finalizerProc*/);

   redis.c文件中的serverCron会进行一些列的操作来保证Redis正常运行。

  aeCreateFileEvent

  调用aeCreateFileEvent函数的目的是执行epoll_ctl系统调用,以便将由anetTcpServer函数创建的监听描述符加入到EPOLLIN事件队列中。同时将它和aeCreateEventLoop函数调用生成的epoll描述符相关连。

  下边详细解释了当initServer调用aeCreateFileEvent函数时的工作,initServer传递接下来的参数给aeCreateFileEvent函数:

  ①server.el:aeCreateEventLoop建立的事件循环。epoll描述符从server.el中获得。

  ②server.fd:负责监听的描述符,同时作为访问相关的文件事件结构体的索引。

  ③AE_READABLE:标志server.fd必须被监视EPOLLIN事件。

  ④acceptHandler:当监视的事件到达时要执行的函数。函数指针存储在eventLoop->events[server.fd]->rfileProc。

  这样就完成了Redis的事件循环。

  处理事件循环

  redis.c文件中的main函数调用ae.c中的aeMain,处理前一阶段初始化完毕的事件循环。

  ae.c文件中的aeMain函数调用ae.c文件中的aeProcessEvent函数,在一个循环中处理时间到期和文件事件。

  aeProcessEvents

  aeProcessEvents函数调用aeSearchNearestTimer函数来查询事件循环中最先要过期的事件。我们的事例中只有一个事件那就是通过调用aeCreateTimeEvent函数建立的。

  记住,如果将超时时间设定为1毫秒,那么通过aeCreateTimeEvent函数建立的定时器事件很可能会被忽略。

  和事件循环相关连的tvp结构体被传递给ae_epoll.c文件中的aeApiPoll函数。aeApiPoll函数在epoll描述符上进行epoll_wait,同时想下边描述的方式激发eventLoop->fired表。

  fd:根据掩码值此时准备好读/写的描述符。

  mask:读/写操作可以在对应的描述符上进行。

  aeApiPoll函数返回准备好的文件描述符个数。现在我们总结一下,当有客户端请求到来时候,aeApiPoll函数会发现并且使用一个正在监听的描述符实体和AE——READABLE掩码激发eventLoop->fired表格。

  现在aeProcessEvents函数调用redis.c文件中已经被注册为回调函数的acceptHandler函数。acceptHandler函数在正在监听的描述符上执行accpet操作,返回一个已经和客户端建立连接的描述符。createClient函数通过调用aeCreateFileEvent函数向已经连接的描述符上添加一个文件事件。如下所示:

if (aeCreateFileEvent(server.el, c->fd, AE_READABLE,
    readQueryFromClient, c)
== AE_ERR) {
    freeClient(c);
    
return NULL;
}

   代码中的c指的是redisClient结构类型的变量,c->fd就是已经建立连接的描述符。

  然后aeProcessEvent函数调用processTimeEvents函数。

  processTimeEvents

  processTimeEvents从时间事件列表开始处eventLoop->timeEventHead开始迭代。

  对于每一个到期的时间事件,processTimeEvents调用相应的已注册的回调函数。本例中仅有一个已注册的回调函数,也就是redis.c文件中的serverCron函数。这个函数返回毫秒数,指示这个回调函数过多长时间再次调用。这写更改可以通过调用aeAddMilliSeconds函数记录,而且会在下一次循环中处理。

  英文原文:Redis Event Library

0
相关文章