暗淡青春|Redis1.0源码阅读笔记一、总体流程( 二 )


static void initServer() {int j;signal(SIGHUP, SIG_IGN);signal(SIGPIPE, SIG_IGN);setupSigSegvAction();server.clients = listCreate();server.slaves = listCreate();server.monitors = listCreate();server.objfreelist = listCreate();createSharedObjects();server.el = aeCreateEventLoop();server.db = zmalloc(sizeof(redisDb)*server.dbnum);server.sharingpool = dictCreate(if (!server.db || !server.clients || !server.slaves || !server.monitors || !server.el || !server.objfreelist)oom("server initialization"); /* Fatal OOM */server.fd = anetTcpServer(server.neterr, server.port, server.bindaddr);if (server.fd == -1) {redisLog(REDIS_WARNING, "Opening TCP port: %s", server.neterr);exit(1);}for (j = 0; j < server.dbnum; j++) {server.db[j].dict = dictCreate(server.db[j].expires = dictCreate(server.db[j].id = j;}server.cronloops = 0;server.bgsaveinprogress = 0;server.bgsavechildpid = -1;server.lastsave = time(NULL);server.dirty = 0;server.usedmemory = 0;server.stat_numcommands = 0;server.stat_numconnections = 0;server.stat_starttime = time(NULL);aeCreateTimeEvent(server.el, 1000, serverCron, NULL, NULL);}aeMainaeMain是Redis处理逻辑的主循环 , 退出循环的标记是eventLoop->stop不等于零 , 具体的逻辑处理 , 是由函数aeProcessEvents完成的 。
void aeMain(aeEventLoop *eventLoop){eventLoop->stop = 0;while (!eventLoop->stop)aeProcessEvents(eventLoop, AE_ALL_EVENTS);}eventLoop是全局变量server的el字段 , 其类型是结构体aeEventLoop 。
/* State of an event based program */typedef struct aeEventLoop {long long timeEventNextId;aeFileEvent *fileEventHead;aeTimeEvent *timeEventHead;int stop;} aeEventLoop;接下来 , 我们要重点看一下函数aeProcessEvents具体做了哪些事 。
首先 , 遍历链表fileEventHead , 分别获得AE_READABLE、AE_WRITABLE、AE_EXCEPTION三类的集合 。
aeFileEvent *fe = eventLoop->fileEventHead;/* Check file events */if (flagsif (fe->maskif (fe->maskif (maxfd < fe->fd) maxfd = fe->fd;numfd++;fe = fe->next;}}接着 , 计算最近一个时间事件触发的剩余时间tv , 用该时间当做select的timeout参数
if (flags if (shortest) {long now_sec, now_ms;/* Calculate the time missing for the nearest* timer to fire. */aeGetTime(tvp =tvp->tv_sec = shortest->when_sec - now_sec;if (shortest->when_ms < now_ms) {tvp->tv_usec = ((shortest->when_ms+1000) - now_ms)*1000;tvp->tv_sec --;} else {tvp->tv_usec = (shortest->when_ms - now_ms)*1000;}} else {/* If we have to check for events but need to return* ASAP because of AE_DONT_WAIT we need to se the timeout* to zero */if (flagstvp =} else {/* Otherwise we can block */tvp = NULL; /* wait forever */}}调用select , 获得可读、可写的文件描述符数量 。 如果有可读写的文件描述符 , 则遍历eventLoop中的链表fileEventHead , 依次调用每个节点的fielProc函数 。 fileEventHead链表的每个节点 , 类型是struct aeFileEvent, 创建节点的函数是:int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData, aeEventFinalizerProc *finalizerProc) 。函数参数的proc , 指定了节点的fileProc实现 。 通过全局搜索调用函数aeCreateFileEvent的地方 , 我们可以知道 , 节点的fileProc的具体实现 , 包括以下四种:readQueryFromClient、sendReplyToClient、sendBulkToSlave、acceptHandler 。


推荐阅读