文章目录
- 前言
- 一、SDS介绍
- 1.SDS定义
- 2.柔性数组简介
- 二、SDS和c语言字符串对比
- 1.SDS可以常数时间获取字符串长度
- 2.SDS可以杜绝缓冲区溢出
- 3.减少修改字符串带来的内存重分配次数
- 4.SDS是二进制安全的
- 5.SDS支持部分c函数
- 三、Redis zmalloc 分析
- 四、Redis SDS源码剖析
- 1.获取len free函数
- 2.初始化SDS字符串函数
- 3.SDS内存扩展函数
- 总结
前言
本文对Redis的简单动态字符串(simple dynamic string)进行了简要介绍,并结合sds对Redis的内存分配释放api进行分析,涉及的源码文件为sds.h、sds.c、zmalloc.h、zmalloc.c,源码下载地址为https://github.com/readywang/Redis3.0。
一、SDS介绍
1.SDS定义
SDS全称为简单动态字符串,是Redis中为了表示字符串对象定义的一种数据结构。源码sds.h定义的sdshdr结构表示的就是简单动态字符串,定义如下:
代码语言:javascript复制/*
* 保存字符串对象的结构
*/
struct sdshdr {
// buf 中已占用空间的长度
int len;
// buf 中剩余可用空间的长度
int free;
// 数据空间
char buf[];
};
一个实际的sds对象示意图如下图所示:
其中,buf是存放字符串的首地址,字符串也是以空字符( )结尾,这点和c语言字符串类似。len表示buf中字符串占用的字节数,不包括末尾空字符,free表示空闲的字节数。整个buf大小等于len free 1,1代表空字符。
2.柔性数组简介
C语言标准C99 中,结构中的最后一个元素允许是未知大小的数组,这个元素称为柔性数组,sdshdr中的buf就是柔性数组。柔性数组有以下几个特点: 1、结构中的柔性数组成员前面必须至少一个其他成员。 2、sizeof 返回的这种结构大小不包括柔性数组的内存。 3、包含柔性数组成员的结构用malloc ()函数进行内存的动态分配。 在解释以上几点之前,可以对比一下下面结构体和上面结构体的区别,可以发现只是将柔性数组buf换成了指针pBuf。下面结合这两个结构体分析一下柔性数组特点。
代码语言:javascript复制struct sdshdrPtr {
// buf 中已占用空间的长度
int len;
// buf 中剩余可用空间的长度
int free;
// 数据空间
char *pBuf;
};
第一点非常容易理解。对于第二点,可以输出sizeof(sdshdr)的值,一般是8,发现并不包括buf占用的内存。而如果sizeof(sdshdrPtr),值是12,包括了4字节的pBuf指针大小。这也是柔性数组相比指针的一大优点:可以节省内存。对于第三点,柔型数组使用时一般根据len属性动态分配内存,如分配一个sdshdr对象来存放字符串的代码如下所示:
代码语言:javascript复制 char *pStr = "Redis is too easy!"; //待存储字符串
int len = strlen(pStr);
sdshdr *pSds = (sdshdr *)malloc(sizeof(sdshdr) len 1); //预留空字符
pSds->len = len;
pSds->free = 0;
memcpy(pSds->buf, pStr, len);
pSds->buf[len] = '