|
现在我们分析Redis从启动开始的执行流程,从而顺藤摸瓜地理解其事件驱动模型。
首先找到main入口:
- int main(int argc, char **argv) {
- time_t start;
- initServerConfig();
- if (argc == 2) {
- if (strcmp(argv[1], "-v") == 0 ||
- strcmp(argv[1], "--version") == 0) version();
- if (strcmp(argv[1], "--help") == 0) usage();
- resetServerSaveParams();
- loadServerConfig(argv[1]);
- } 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 原文链接
|
|