Redis源码分析系列九:aeMain(server.el)

很高兴,咱们历尽艰难险阻,来到了函数aeMain(server.el) api

这个函数是主循环函数,源码以下: 数组

void aeMain(aeEventLoop *eventLoop)
{
    eventLoop->stop = 0;
    while (!eventLoop->stop) {
        if (eventLoop->beforesleep != NULL)
            eventLoop->beforesleep(eventLoop);
        aeProcessEvents(eventLoop, AE_ALL_EVENTS);
    }
}

 

~~~~~~~~~~~~~~ 服务器

eventLoop->stop = 0;//设置stop标志为0 socket

 eventLoop->beforesleep(eventLoop);还不到分析的时候,暂且不分析。  函数

毕竟如今尚未数据,如今分析也无法分析,后面就能够了。 oop

aeProcessEvents(eventLoop, AE_ALL_EVENTS);//处理各类事件 spa

让咱们去关注如何执行的。 code

~~~~~~~~~~~~~~~~~ server

/* Nothing to do? return ASAP */
    if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;

//若是任何一种事件都不处理,则返回 对象

其实这个函数是处理2种行为的,来看具体的原理。

有些地方暂时不说,

主要先关注aeApiPoll(eventLoop, tvp);

显然是从以前的监听端口中accept出一个链接来处理。

这个函数内部经过retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,
            tvp ? (tvp->tv_sec*1000 + tvp->tv_usec/1000) : -1);

来获取可accept的对象。

重点关注下面两行:

eventLoop->fired[j].fd = e->data.fd;
eventLoop->fired[j].mask = mask;

也就是先把能够处理的socket存储在fired数组里。

~~~~~~~~~~~~~~~

接着执行下面这个代码:

for (j = 0; j < numevents; j++)
  {
            aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
            int mask = eventLoop->fired[j].mask;
            int fd = eventLoop->fired[j].fd;
            int rfired = 0;

     /* note the fe->mask & mask & ... code: maybe an already processed
             * event removed an element that fired and we still didn't
             * processed, so we check if the event is still valid. */
            if (fe->mask & mask & AE_READABLE) {
                rfired = 1;
                fe->rfileProc(eventLoop,fd,fe->clientData,mask);
            }
            if (fe->mask & mask & AE_WRITABLE) {
                if (!rfired || fe->wfileProc != fe->rfileProc)
                    fe->wfileProc(eventLoop,fd,fe->clientData,mask);
            }
            processed++;
        }

咱们来看具体的执行过程。

aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];

这个代码的做用是取出events对象,若是读者这个时候去观察events数组,就知道以前这个数组的样子是这样的:

aeFileEvent *events; /* Registered events */
 //( server.maxclients+REDIS_EVENTLOOP_FDSET_INCR )  *  sizeof(aeFileEvent)
 //下标与句柄ID相同
 //且每一个event.mask = AE_NONE|AE_READABLE 、、
 //           .rfileProc = acceptTcpHandler
    //.clientData= NULL

也就是说,存储了mask和读处理函数。

~~~~~~

int mask = eventLoop->fired[j].mask;

mask标志了当前socket能够作的事情。

 int fd = eventLoop->fired[j].fd;、、标志了当前socket的句柄号。

~~~~

if (fe->mask & mask & AE_READABLE)
   {
    //若是能够读

    
                rfired = 1;//记忆是否曾经有可读的socket

    
                fe->rfileProc(eventLoop,fd,fe->clientData,mask);

                    //触发读函数。
 }
对于监听server socket来讲,读函数为:acceptTcpHandler

显然里面会调用accept来获取客户链接服务器的链接并加入到server->el.apidata.fd中去监听。

洗澡,而后睡觉!

相关文章
相关标签/搜索