Redis源码剖析(1)-动态字符串sds

来源:互联网
更新时间:2017/1/23 6:21:51
责任编辑:王亮
字体:

一直对redis源码感兴趣,工作之余,总是抽空阅读,在这里记录下自己的阅读心得。废话不多说,一起来看下redis内部比较简单的数据结构–简单动态字符串SDS,源文件为sds.c和sds.h。

SDS数据结构定义

struct sdshdr {
    // 当前字符串的长度(不包括‘\0’)
    int len;
    // buf 中剩余可用空间的长度
    int free;
    // 字符数组
    char buf[];
};

Redis没有采用C语言中的字符串表示方式(以‘\0’结尾的字符数组),而是构建了SDS这种数据结构作为Redis默认的字符串,相对于C语言传统的字符串的好处在于:可动态地扩展内存、二进制安全和兼容部分C字符串函数。

基本操作函数

1、sds创建函数-sdsnewlen
//类型别名,用于指向 sdshdr 的 buf 属性
typedef char *sds;
sds sdsnewlen(const void *init, size_t initlen) {
    struct sdshdr *sh;
    // 根据是否有初始化内容,选择适当的内存分配方式
    //+1是因为需要额外的一个字节存放'\0'
    if (init) {
        // zmalloc 不初始化所分配的内存
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
    } else {
        // zcalloc 将分配的内存全部初始化为 0
        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
    }
    // 内存分配失败,返回
    if (sh == NULL) return NULL;
    // 设置初始化长度
    sh->len = initlen;
    // 新 sds 不预留任何空间
    sh->free = 0;
    // 如果有指定初始化内容,将它们复制到 sdshdr 的 buf 中
    if (initlen && init)
        memcpy(sh->buf, init, initlen);
    sh->buf[initlen] = '\0';
    // 返回 buf 部分,而不是整个 sdshdr
    return (char*)sh->buf;
}

需要注意的是函数的返回值:sh->buf,sds的很多基本操作都是先

通过sh->buf找到sdshdr结构体,例如接下去说到的sdslen。

2、获取sds中字符串的长度-sdslen
/* 获取字符串长度 */
static inline size_t sdslen(const sds s) {
    /* sizeof(struct sdshdr))的长度是8,而s指向sdshdr中的buf字符数组,所以 s-8 的结果就是sdshdr结构体的地址--sh,通过sh->len就可以获得字符串的长度
    */
    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
    return sh->len;
}

类似的函数操作还有sdsavail–获取sds可用空间的长度等。

3、空间扩展函数-sdsMakeRoomFor
//最大预分配长度
#define SDS_MAX_PREALLOC (1024*1024)
//s 需要扩展空间的sdshdr,addlen 需要扩展的字节数
sds sdsMakeRoomFor(sds s, size_t addlen) {
    struct sdshdr *sh, *newsh;
    // sdsavail()函数可以获取 s 目前的空余空间长度
    size_t free = sdsavail(s);
    size_t len, newlen;
    // s 中有够用的字节空间,直接返回
    if (free >= addlen) return s;
    // 获取 s 目前已占用空间的长度
    len = sdslen(s);
    sh = (void*) (s-(sizeof(struct sdshdr)));
    // s 最少需要的长度
    newlen = (len+addlen);
    // 根据新长度,为 s 分配新空间所需的大小
    if (newlen < SDS_MAX_PREALLOC)
        // 如果新长度小于 1M
        newlen *= 2;
    else
        // 否则,多分配1M的空间
        newlen += SDS_MAX_PREALLOC;
    newsh = realloc(sh, sizeof(struct sdshdr)+newlen+1);
    // 内存不足,分配失败,返回
    if (newsh == NULL) return NULL;
    // 更新 sds 的空余长度
    newsh->free = newlen - len;
    // 返回 sds
    return newsh->buf;
}

未完,待续~

www.xue163.com true /3960/39607432.html report 2894 Redis源码剖析(1)-动态字符串sds,一直对redis源码感兴趣,工作之余,总是抽空阅读,在这里记录下自己的阅读心得。废话不多说,一起来看下redis内部比较简单的数据结构–简单动态字符串SDS,源文件为sds.c和sds.h。SDS数据结构定义structsdshdr{//当前字符串的...
最近关注
首页推荐
热门图片
最新添加资讯
24小时热门资讯
精彩资讯
精彩推荐
热点推荐
真视界
精彩图片
社区精粹
关于本站 | 广告服务 | 手机版 | 商务合作 | 免责申明 | 招聘信息 | 联系我们
Copyright © 2004-2016 Xue163.com All Rights Reserved. 学网 版权所有
京ICP备10044368号-1 京公网安备11010802011102号
荐闻 | 学网头条知识问答 | 装修 | 作业 | 荐闻 | 学网头条精彩微信 | 新闻中心 | 软件教室 | 设计大全 | 网络相关 | 英语学习 | 开发编程 | 考试中心 | 参考范文 | 管理文库 | 营销中心 | 站长之家 | IT信息中心 | 商学院 | 数码大全 | 硬件DIY | 企业服务 | 网吧在线 | 问吧 | 百科 | 硬件知识 | 本网视点 | 文库 | 手机 | 平板 | 汽车 | 游戏 | 家电 | 精彩摄影 | 时尚科技 | 现代家居 | IT女人 | 经验 | 每日新闻 | 健康养生 | 图书馆 | 猎奇 | 精彩看点 | 图库 | 新闻中心 | 软件教室 | 设计大全 | 网络相关 | 英语学习 | 开发编程 | 考试中心 | 参考范文 | 管理文库 | 营销中心 | 站长之家 | IT信息中心 | 商学院 | 数码大全 | 硬件DIY | 企业服务 | 网吧在线 | 问吧 | 百科 | 硬件知识 | 本网视点 | 文库 | 手机 | 平板 | 汽车 | 游戏 | 家电 | 精彩摄影 | 时尚科技 | 现代家居 | IT女人 | 经验 | 每日新闻 | 健康养生 | 图书馆 | 精彩微信 | 猎奇 | 精彩看点 | 图库编程 方案 信息windows方案windows answer文档机构教育文档问答中心IT编程数码信息解决方案信息中心IT科技