redis自顶向下源码阅读(二)——服务器初始化
先放出主函数前面一段的代码
int main(int argc, char **argv) {
struct timeval tv;
/* We need to initialize our libraries, and the server configuration. */
#ifdef INIT_SETPROCTITLE_REPLACEMENT
spt_init(argc, argv);
#endif
setlocale(LC_COLLATE,"");
zmalloc_enable_thread_safeness();
zmalloc_set_oom_handler(redisOutOfMemoryHandler);
srand(time(NULL)^getpid());
gettimeofday(&tv,NULL);
dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());
server.sentinel_mode = checkForSentinelMode(argc,argv);
initServerConfig();
if (server.sentinel_mode) {
initSentinelConfig();
initSentinel();
}
1. 初始化 SPT 数据结构
-
代码
#ifdef INIT_SETPROCTITLE_REPLACEMENT spt_init(argc, argv); #endif
-
含义
对命令行中的
argv
字符串数组进行处理,argv
的结构如下argv[0] argv[1] environ[0] environ[1] a \0 b \0 d=2\0 e=3\0 0 1 2 3 4567 891011
执行这个函数是因为之后需要设置进程名,即
argv[0]
,但是因为命令行输入进来的argv[]
数组在内存上是相邻的,且argv[0]
的长度是固定的,那么一旦给argv[0]
重新设置,那么字符长度超了怎么办,所以另外开辟了内存,把argv[0]
后面的数据存到新开辟的内存地区,所以argv[0]
可使用的内存大小相当于进行了一次扩展。其中的argv[1-n]
就存到了SPT中。 -
SPT 结构和 envp
// setprocitle.c 文件中定义 extern char **environ; static struct { /* original value */ const char *arg0; /* title space available */ char *base, *end; /* pointer to original nul character within base */ char *nul; _Bool reset; int error; } SPT;
-
参考
详情可参考:https://www.jianshu.com/p/36c301ac87df
2. setlocale
// http://c.biancheng.net/ref/setlocale.html
setlocale(LC_COLLATE,"");
3. 配置 zmalloc
设置内存分配管理的线程安全变量。
zmalloc_enable_thread_safeness();
设置成功后,一旦进行zmalloc
相关操作时,程序都会上进程安全锁。例如:
if (zmalloc_thread_safe) {
#if defined(__ATOMIC_RELAXED) || defined(HAVE_ATOMIC)
um = update_zmalloc_stat_add(0);
#else
pthread_mutex_lock(&used_memory_mutex);
um = used_memory;
pthread_mutex_unlock(&used_memory_mutex);
#endif
}
设置内存溢出时的错误处理器
zmalloc_set_oom_handler(redisOutOfMemoryHandler);
4. 配置随机种子
// 用 时间 和 进程识别码 初始化随机数发生器
srand(time(NULL)^getpid());
// 获取时间
gettimeofday(&tv,NULL);
// 设置哈希函数的随机种子,哈希的时候用
dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());
5. 服务器配置初始化
- 由命令行字符串判断这次启动服务器有没有指定sentinel(哨兵)模式
// 由命令行字符串判断 有没有
server.sentinel_mode = checkForSentinelMode(argc,argv);
-
initServerConfig()
-
初始化 sentinel
/* 我们现在需要初始化 sentinel, * 因为在 sentinel 模式下解析配置文件会 * 影响到 sentinel 的主节点填充 sentinel 数据结构。 */ if (server.sentinel_mode) { initSentinelConfig(); initSentinel(); }
这两个初始化挺长的,就下一篇讲吧~
总体结构参考:https://www.cnblogs.com/chenpingzhao/p/5229129.html