【redis6.0.6】redis源码慢慢学,慢慢看 -- 第四天:提纲掣领main函数(server)

举报
看,未来 发表于 2020/12/29 23:09:40 2020/12/29
【摘要】 文章目录 前言: Redis MakefileCopyright (C) 2009 Salvatore Sanfilippo This file is released under the BSD license, see the COPYING file探索main函数第一块第二块第三块第四块第五块 第六块第七块 前言: 先附上人家的...

在这里插入图片描述

前言:

先附上人家的版权:

Redis Makefile

Copyright © 2009 Salvatore Sanfilippo

This file is released under the BSD license, see the COPYING file

redis和STL不同,这是一个完整项目,有头有尾,STL是一套组件,开箱即用。而阅读一个项目的源码,是不是应该从main函数入手,尽管大部分函数不知道怎么实现的,那又如何?字面意思不是很明显嘛,高内聚。

所以我决定,从main入手,全面铺开。

探索main函数

函数全貌我就不放出来了,太大块

一块一块来。

第一块

#ifdef REDIS_TEST if (argc == 3 && !strcasecmp(argv[1], "test")) { if (!strcasecmp(argv[2], "ziplist")) { return ziplistTest(argc, argv); } else if (!strcasecmp(argv[2], "quicklist")) { quicklistTest(argc, argv); } else if (!strcasecmp(argv[2], "intset")) { return intsetTest(argc, argv); } else if (!strcasecmp(argv[2], "zipmap")) { return zipmapTest(argc, argv); } else if (!strcasecmp(argv[2], "sha1test")) { return sha1Test(argc, argv); } else if (!strcasecmp(argv[2], "util")) { return utilTest(argc, argv); } else if (!strcasecmp(argv[2], "endianconv")) { return endianconvTest(argc, argv); } else if (!strcasecmp(argv[2], "crc64")) { return crc64Test(argc, argv); } else if (!strcasecmp(argv[2], "zmalloc")) { return zmalloc_test(argc, argv); } return -1; /* test not found */ }
#endif

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

明眼人都知道它是干嘛用的吧,我就不多说啦。

第二块

#ifdef INIT_SETPROCTITLE_REPLACEMENT spt_init(argc, argv);
#endif

  
 
  • 1
  • 2
  • 3

初始化库

第三块

	setlocale(LC_COLLATE,"");	//更改字符编码 tzset(); /* Populates 'timezone' global. */ zmalloc_set_oom_handler(redisOutOfMemoryHandler);	//oom时的处理,主要是内存不足时,将需要的memory的值打印出来 srand(time(NULL)^getpid());	// 根据当前时间和pid获取随机值的 gettimeofday(&tv,NULL);		// 1970年1月1日到现在的时间 crc64_init();

	//哈希种子
	uint8_t hashseed[16]; getRandomBytes(hashseed,sizeof(hashseed)); dictSetHashFunctionSeed(hashseed); // 检查服务器是否以 Sentinel 模式启动 server.sentinel_mode = checkForSentinelMode(argc,argv);

	// 初始化服务器 initServerConfig(); ACLInit(); /* The ACL subsystem must be initialized ASAP because the basic networking code and client creation depends on it. */ moduleInitModulesSystem(); tlsInit();

	/* Store the executable path and arguments in a safe place in order * to be able to restart the server later. */ server.executable = getAbsolutePath(argv[0]); server.exec_argv = zmalloc(sizeof(char*)*(argc+1)); server.exec_argv[argc] = NULL; for (j = 0; j < argc; j++) server.exec_argv[j] = zstrdup(argv[j]);

	// 如果服务器以 Sentinel 模式启动,那么进行 Sentinel 功能相关的初始化 // 并为要监视的主服务器创建一些相应的数据结构 if (server.sentinel_mode) { initSentinelConfig(); initSentinel(); }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

诸位都亲眼目睹咯,一堆的初始化工作。

第四块

检查是否要以redis-check-rdb/aof方式启动

	if (strstr(argv[0],"redis-check-rdb") != NULL) redis_check_rdb_main(argc,argv,NULL); else if (strstr(argv[0],"redis-check-aof") != NULL) redis_check_aof_main(argc,argv); //检查用户是否指定了配置文件,或者配置选项
	if (argc >= 2) { j = 1; /* First option to parse in argv[] */ sds options = sdsempty(); char *configfile = NULL;

	//处理特殊选项 -h 、-v 和 --test-memory /* Handle special options --help and --version */ if (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version") == 0) version(); if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) usage(); if (strcmp(argv[1], "--test-memory") == 0) { if (argc == 3) { memtest(atoi(argv[2]),50); exit(0); } else { fprintf(stderr,"Please specify the amount of memory to test in megabytes.\n"); fprintf(stderr,"Example: ./redis-server --test-memory 4096\n\n"); exit(1); } }

// 如果第一个参数(argv[1])不是以 "--" 开头,那么它应该是一个配置文件 if (argv[j][0] != '-' || argv[j][1] != '-') { configfile = argv[j]; server.configfile = getAbsolutePath(configfile); /* Replace the config file in server.exec_argv with * its absolute path. */ zfree(server.exec_argv[j]); server.exec_argv[j] = zstrdup(server.configfile); j++; } // 对用户给定的其余选项进行分析,并将分析所得的字符串追加稍后载入的配置文件的内容之后
		// 比如 --port 6380 会被分析为 "port 6380\n"
		while(j != argc) { if (argv[j][0] == '-' && argv[j][1] == '-') { /* Option name */ if (!strcmp(argv[j], "--check-rdb")) { /* Argument has no options, need to skip for parsing. */ j++; continue; } if (sdslen(options)) options = sdscat(options,"\n"); options = sdscat(options,argv[j]+2); options = sdscat(options," "); } else { /* Option argument */ options = sdscatrepr(options,argv[j],strlen(argv[j])); options = sdscat(options," "); } j++; } if (server.sentinel_mode && configfile && *configfile == '-') { serverLog(LL_WARNING, "Sentinel config from STDIN not allowed."); serverLog(LL_WARNING, "Sentinel needs config file on disk to save state.  Exiting..."); exit(1); } resetServerSaveParams();	 // 重置保存条件 loadServerConfig(configfile,options);	// 载入配置文件, options 是前面分析出的给定选项 sdsfree(options); }


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

可以看出,是一些开机自选项的配置

第五块

 serverLog(LL_WARNING, "oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo"); serverLog(LL_WARNING, "Redis version=%s, bits=%d, commit=%s, modified=%d, pid=%d, just started", REDIS_VERSION, (sizeof(long) == 8) ? 64 : 32, redisGitSHA1(), strtol(redisGitDirty(),NULL,10) > 0, (int)getpid()); if (argc == 1) { serverLog(LL_WARNING, "Warning: no config file specified, using the default config. In order to specify a config file use %s /path/to/%s.conf", argv[0], server.sentinel_mode ? "sentinel" : "redis"); } else { serverLog(LL_WARNING, "Configuration loaded"); } server.supervised = redisIsSupervised(server.supervised_mode); int background = server.daemonize && !server.supervised; if (background) daemonize();

	server.supervised = redisIsSupervised(server.supervised_mode); int background = server.daemonize && !server.supervised; if (background) daemonize(); //sever端的初始化 initServer(); // 设置进程的title if (background || server.pidfile) createPidFile(); redisSetProcTitle(argv[0]); redisAsciiArt(); checkTcpBacklogSettings();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

第六块

// 如果服务器不是运行在 SENTINEL 模式,那么执行以下代码
if (!server.sentinel_mode) { /* Things not needed when running in Sentinel mode. */ serverLog(LL_WARNING,"Server initialized"); #ifdef __linux__ linuxMemoryWarnings();	// 打印内存警告 #endif moduleLoadFromQueue(); ACLLoadUsersAtStartup(); InitServerLast(); loadDataFromDisk();	// 从 AOF 文件或者 RDB 文件中载入数据 if (server.cluster_enabled) {	// 启动集群? if (verifyClusterConfigWithData() == C_ERR) { serverLog(LL_WARNING, "You can't have keys in a DB different than DB 0 when in " "Cluster mode. Exiting."); exit(1); } } if (server.ipfd_count > 0 || server.tlsfd_count > 0) serverLog(LL_NOTICE,"Ready to accept connections"); if (server.sofd > 0) serverLog(LL_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket); if (server.supervised_mode == SUPERVISED_SYSTEMD) { if (!server.masterhost) { redisCommunicateSystemd("STATUS=Ready to accept connections\n"); redisCommunicateSystemd("READY=1\n"); } else { redisCommunicateSystemd("STATUS=Waiting for MASTER <-> REPLICA sync\n"); } } } else { InitServerLast(); sentinelIsRunning(); // 检测sentinel的配置是否有效 if (server.supervised_mode == SUPERVISED_SYSTEMD) { redisCommunicateSystemd("STATUS=Ready to accept connections\n"); redisCommunicateSystemd("READY=1\n"); } }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

第七块

 // 检查不正常的 maxmemory 配置 if (server.maxmemory > 0 && server.maxmemory < 1024*1024) { serverLog(LL_WARNING,"WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?", server.maxmemory); }

 // 运行事件处理器,一直到服务器关闭为止 redisSetCpuAffinity(server.server_cpulist); aeMain(server.el); aeDeleteEventLoop(server.el);	// 服务器关闭,停止事件循环 return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

喔,累,这两天忙着回学校加复习,两天没更了。

如果觉得还阔以,阔以来个赞评关注哦!
在这里插入图片描述

文章来源: lion-wu.blog.csdn.net,作者:看,未来,版权归原作者所有,如需转载,请联系作者。

原文链接:lion-wu.blog.csdn.net/article/details/108327262

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。