x相关源码:ae.h ae.c networking.c anet.c net.h ae_epoll.c ae_select.c ae_kqueue.c
ae.h、ae.c :event library具体实现
networking.c : 与客户端的交互
anet.h anet.c : 网络通信
ae_epoll.c ae_select.c ae_kqueue.c : 不同系统多路IO封装
ae_epoll.c : linux平台
ae_select.c :unix平台
ae_kqueue.c : BSD、APPLE
根据操作系统进行多路IO类型选择,linux系统选择为epoll:
#ifdef __linux__ #define HAVE_EPOLL 1 #endif #if (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__) #define HAVE_KQUEUE 1 #endif #ifdef __sun #include <sys/feature_tests.h> #ifdef _DTRACE_VERSION #define HAVE_EVPORT 1 #endif #endif
#ifdef HAVE_EVPORT #include "ae_evport.c" #else #ifdef HAVE_EPOLL #include "ae_epoll.c" #else #ifdef HAVE_KQUEUE #include "ae_kqueue.c" #else #include "ae_select.c" #endif #endif #endif
if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE, acceptTcpHandler,NULL) == AE_ERR) oom("creating file event"); if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE, acceptUnixHandler,NULL) == AE_ERR) oom("creating file event");2. 回调函数acceptTcpHandler/acceptUnixHandler
void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) { ...... nread = read(fd, c->querybuf+qblen, readlen); ...... if (nread) { sdsIncrLen(c->querybuf,nread); c->lastinteraction = server.unixtime; if (c->flags & REDIS_MASTER) c->reploff += nread; } else { server.current_client = NULL; return; } ...... }3. 客户端请求处理:
void processInputBuffer(redisClient *c) { while(sdslen(c->querybuf)) { ...... //分析请求 if (c->argc == 0) { resetClient(c); } else { if (processCommand(c) == REDIS_OK) resetClient(c); } } }
void aeMain(aeEventLoop *eventLoop) { eventLoop->stop = 0; while (!eventLoop->stop) { if (eventLoop->beforesleep != NULL) eventLoop->beforesleep(eventLoop); aeProcessEvents(eventLoop, AE_ALL_EVENTS); } }beforesleep通过aeSetBeforeSleepProc定义,主要是特殊处理vm和aof相关的请求