2019独角兽企业重金招聘Python工程师标准>>>
server.db = zmalloc(sizeof(redisDb)*server.dbnum);
//开辟缓冲区
listenToPort(server.port,server.ipfd,&server.ipfd_count);
显然这个函数是监听端口
跟踪这个函数,进入,发现最终是掉用_anetTcpServer函数。
下面是_anetTcpServer函数的解析。
static int _anetTcpServer(char *err, int port, char *bindaddr, int af)
{
int s, rv;
char _port[6]; /* strlen("65535") */
//监听端口
struct addrinfo hints;
//.ai_family = AF_INET;
//.ai_socktype = SOCK_STREAM;
//.ai_flags = AI_PASSIVE;
struct addrinfo *servinfo;
struct addrinfo *p;
snprintf(_port,6,"%d",port);
memset(&hints,0,sizeof(hints));
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; /* No effect if bindaddr != NULL */
if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) {
anetSetError(err, "%s", gai_strerror(rv));
return ANET_ERR;
//获取解析的信息链表
}
for (p = servinfo; p != NULL; p = p->ai_next)
{
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
continue;
//创建一个socket
if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error;
if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;
//设置socket重用
if (anetListen(err,s,p->ai_addr,p->ai_addrlen) == ANET_ERR) goto error;
//bind & listen
goto end;
}
if (p == NULL) {
anetSetError(err, "unable to bind socket");
goto error;
}
error:
s = ANET_ERR;
end:
freeaddrinfo(servinfo);
return s;
}
总结:实现了socket,bind,listen并对socket设置了一些优化措施,比如设置passive,重用等。
成功的socket存于server.ipfd,个数由server.ipfd_count指示。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
下面的代码
/* Open the listening Unix domain socket. */if (server.unixsocket != NULL) {
unlink(server.unixsocket); /* don't care if this fails */
server.sofd = anetUnixServer(server.neterr,server.unixsocket,server.unixsocketperm);
if (server.sofd == ANET_ERR) {
redisLog(REDIS_WARNING, "Opening socket: %s", server.neterr);
exit(1);
}
}
用于建立unix 域socket
刚才特意看了配置文件
# Specify the path for the unix socket that will be used to listen for# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 755
我认为这里没有使用domain socket.所以忽略不计。
/* Abort if there are no listening sockets at all. */if (server.ipfd_count == 0 && server.sofd < 0) {
redisLog(REDIS_WARNING, "Configured to not listen anywhere, exiting.");
exit(1);
}
这个只是检查而已,继续往下看。
然后接下来的几行代码采用了dictCreate,还记得之前说过的模板么?
我找到了我的模板,然后替换几个参数,让若干变量得以顺利初始化。
listSetFreeMethod(server.pubsub_patterns,freePubsubPattern);设置server.pubsub_patterns->free = freePubsubPattern
listSetMatchMethod(server.pubsub_patterns,listMatchPubsubPattern);设置 server.pubsub_patterns->match = listMatchPubsubPattern
剩下的若干初始化就很简单,不用多说,代码如下:
server.cronloops = 0;
server.rdb_child_pid = -1;
server.aof_child_pid = -1;
aofRewriteBufferReset();
server.aof_buf = sdsempty();
server.lastsave = time(NULL); /* At startup we consider the DB saved. */
server.lastbgsave_try = 0; /* At startup we never tried to BGSAVE. */
server.rdb_save_time_last = -1;
server.rdb_save_time_start = -1;
server.dirty = 0;
server.stat_numcommands = 0;
server.stat_numconnections = 0;
server.stat_expiredkeys = 0;
server.stat_evictedkeys = 0;
server.stat_starttime = time(NULL);
server.stat_keyspace_misses = 0;
server.stat_keyspace_hits = 0;
server.stat_peak_memory = 0;
server.stat_fork_time = 0;
server.stat_rejected_conn = 0;
server.stat_sync_full = 0;
server.stat_sync_partial_ok = 0;
server.stat_sync_partial_err = 0;
memset(server.ops_sec_samples,0,sizeof(server.ops_sec_samples));
server.ops_sec_idx = 0;
server.ops_sec_last_sample_time = mstime();
server.ops_sec_last_sample_ops = 0;
server.unixtime = time(NULL);
server.mstime = mstime();
server.lastbgsave_status = REDIS_OK;
server.repl_good_slaves_count = 0;