文档章节

Redis源码分析系列六:initserver中

强子1985
 强子1985
发布于 2013/10/17 23:50
字数 580
阅读 171
收藏 0

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;

 

© 著作权归作者所有

共有 人打赏支持
强子1985

强子1985

粉丝 890
博文 1257
码字总数 931987
作品 8
南京
架构师
私信 提问
Redis网络架构及单线程模型

最近略有闲暇时间,于是对Redis进行了一些学习,学习途径除了官方文档还有Redis源代码,我看的版本是2.8.13,Redis源码总行数不到5W行,不同组件拆分非常细致,阅读起来也很清晰。这篇博客主...

Float_Luuu
2016/05/20
1K
0
Redis源码分析系列七:initServer下

这个函数快到尾声了,一鼓作气! if(aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) { redisPanic("Can't create the serverCron time event."); exit(1); } 这个函数......

强子哥哥
2013/10/18
0
0
深入Redis内部-Redis 源码讲解

作者:nosqlfan on 星期一, 三月 7, 2011 · 评论本文 【阅读:4,036 次】 Redis 作为 NoSQL 数据库的杰出代表,一直广受关注,其轻量级的敏捷架构,向来有存储中的瑞士军刀之称。下面推荐的...

Dicky
2011/09/25
0
0
Redis源码分析系列五:initServer上

刚下班,吃了点饭,精神饱满,让我们继续分析initServer,这个函数还是很重要的。 ~~ int j; signal(SIGHUP, SIGIGN);//注册信号处理程序为忽略 signal(SIGPIPE, SIGIGN);//注册信号处理程序...

强子哥哥
2013/10/17
0
0
Redis 的事件驱动库结构

原文地址:http://blog.ddup.us/?p=114 这是一篇翻译文章,原文见这里。Redis实现了它自己的事件库。事件库的实现在ae.c文件中。要弄明白Redis事件库是如何工作的最好的方法就是弄明白Red...

红薯
2011/08/14
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

3.系统和内存架构

在设计程序或并发系统时,需要考虑不同的系统和内存架构风格。 支持并发的计算机系统体系结构 1972年,迈克尔弗林(Michael Flynn)给出了用于分类不同风格计算机系统体系结构的分类法。 该分类...

Eappo_Geng
22分钟前
4
0
今天的学习

1,getimagesize:获得目标图像的大小 2,image_type_to_extension:获得目标文件的后缀信息 3,imagealphablending:设定目标图像混色的模式 4,imagechar:水平的画出一个字符 5,imagecharup...

墨冥
25分钟前
1
0
Java线程中yield与join方法的区别

长期以来,多线程问题颇为受到面试官的青睐。虽然我个人认为我们当中很少有人能真正获得机会开发复杂的多线程应用(在过去的七年中,我得到了一个机会),但是理解多线程对增加你的信心很有用。...

飓风2000
48分钟前
4
0
Python的 is 和 == 弄懂了吗?

在Python中一切都是对象。 Python中对象包含的三个基本要素,分别是: id(身份标识) type(数据类型) value(值) 对象之间比较是否相等可以用 == ,也可以用 is 。 is 和 == 都是对对象进行比较...

上海小胖
49分钟前
2
0
angularJS 路由加载js controller 未定义 解决方案

说明 本文主要说明,在angularJS框架使用中,angularJS 路由加载js controller 未定义 解决方案。 路由 $routeProvider 异步加载js 路由的基本用法,请查看官方文档,下面实例只说明,懒加载...

DrChenXX
57分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部