winston 发表于 2012-3-5 22:49:45

[原]Redis源代码分析之六:Redis执行流程

现在我们分析Redis从启动开始的执行流程,从而顺藤摸瓜地理解其事件驱动模型。
首先找到main入口:

int main(int argc, char **argv) {
    time_t start;

    initServerConfig();
    if (argc == 2) {
      if (strcmp(argv, "-v") == 0 ||
            strcmp(argv, "--version") == 0) version();
      if (strcmp(argv, "--help") == 0) usage();
      resetServerSaveParams();
      loadServerConfig(argv);
    } else if ((argc > 2)) {
      usage();
    } else {
      redisLog(REDIS_WARNING,"Warning: no config file specified, using the default config. In order to specify a config file use 'redis-server /path/to/redis.conf'");
    }
    if (server.daemonize) daemonize();
    initServer();
    if (server.daemonize) createPidFile();
    redisLog(REDIS_NOTICE,"Server started, Redis version " REDIS_VERSION);
#ifdef __linux__
    linuxOvercommitMemoryWarning();
#endif
    start = time(NULL);
    if (server.appendonly) {
      if (loadAppendOnlyFile(server.appendfilename) == REDIS_OK)
            redisLog(REDIS_NOTICE,"DB loaded from append only file: %ld seconds",time(NULL)-start);
    } else {
      if (rdbLoad(server.dbfilename) == REDIS_OK) {
            redisLog(REDIS_NOTICE,"DB loaded from disk: %ld seconds",
                time(NULL)-start);
      } else if (errno != ENOENT) {
            redisLog(REDIS_WARNING,"Fatal error loading the DB. Exiting.");
            exit(1);
      }
    }
    if (server.ipfd > 0)
      redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
    if (server.sofd > 0)
      redisLog(REDIS_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket);
    aeSetBeforeSleepProc(server.el,beforeSleep);
    aeMain(server.el);
    aeDeleteEventLoop(server.el);
    return 0;
}
我们看到,在initServer()中完成了初始化工作:

void initServer() {
    int j;

    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    setupSignalHandlers();

    if (server.syslog_enabled) {
      openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,
            server.syslog_facility);
    }

    server.mainthread = pthread_self();
    server.clients = listCreate();
    server.slaves = listCreate();
    server.monitors = listCreate();
    server.unblocked_clients = listCreate();
    createSharedObjects();
    server.el = aeCreateEventLoop();
    server.db = zmalloc(sizeof(redisDb)*server.dbnum);

    if (server.port != 0) {
      server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr);
…… …… ……
    aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL);
    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");

    if (server.appendonly) {
      server.appendfd = open(server.appendfilename,O_WRONLY|O_APPEND|O_CREAT,0644);
      if (server.appendfd == -1) {
            redisLog(REDIS_WARNING, "Can't open the append-only file: %s",
                strerror(errno));
            exit(1);
      }
    }

    if (server.vm_enabled) vmInit();
    slowlogInit();
    bioInit();
    srand(time(NULL)^getpid());
}
其中在redisServer结构体中定义了:

aeEventLoop *el;于是我们分析事件驱动模型,就可以从aeEventLoop入手,继续追随aeCreateTimeEvent函数和aeCreateFileEvent创建的事件是如何在事件驱动库下工作的。具体见下节。

作者:Aegeaner 发表于2012-2-27 14:09:40 原文链接

页: [1]
查看完整版本: [原]Redis源代码分析之六:Redis执行流程