很高兴,咱们历尽艰难险阻,来到了函数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中去监听。
洗澡,而后睡觉!