很高興,咱們歷盡艱難險阻,來到了函數aeMain(server.el) api
這個函數是主循環函數,源碼以下: 數組
void aeMain(aeEventLoop *eventLoop)
~~~~~~~~~~~~~~ 服務器
eventLoop->stop = 0;//設置stop標誌爲0 socket
eventLoop->beforesleep(eventLoop);還不到分析的時候,暫且不分析。 函數
畢竟如今尚未數據,如今分析也無法分析,後面就能夠了。 oop
aeProcessEvents(eventLoop, AE_ALL_EVENTS);//處理各類事件 spa
讓咱們去關注如何執行的。 code
~~~~~~~~~~~~~~~~~ server
/* Nothing to do? return ASAP *///若是任何一種事件都不處理,則返回 對象
其實這個函數是處理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;也就是先把能夠處理的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中去監聽。
洗澡,而後睡覺!