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中去監聽。

洗澡,而後睡覺!

相關文章
相關標籤/搜索