源码分析章节,我尽量使用原生的redis源码,不去看黄建宏的注释,提高自己阅读源码的能力,此外,redis版本还是3.0
源码下载,大家可以到这 http://download.redis.io/releases/
sdsnew
typedef char *sds;
sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh;
//分配内存
if (init) {
sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
} else {
sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
}
//分配失败返回NULL
if (sh == NULL) return NULL;
sh->len = initlen;
sh->free = 0;//这里可以看到sds初始是不会分配多余空间的。
if (initlen && init)
//如果init中原来有内容则拷贝。
memcpy(sh->buf, init, initlen);
sh->buf[initlen] = '\0';
return (char*)sh->buf;
}
这里有用到zmalloc
和zcalloc
两个函数,具体分析不在赘述。zmalloc
和malloc
的主要区别在于zmalloc
比malloc
多分配了一定的空间(据平台而定),这个多余的空间用来存储zmalloc
本要分配的大小。zcalloc
与zmalloc
的区别在于zmalloc
不会初始化内存,而zcalloc
会初始化。
sdsempty
创建并返回一个只保存了空字符串 ""
的 sds。
sds sdsempty(void) {
return sdsnewlen(“”,0);
}
sdsnew
把一个给定的c字符串转为sds。
sds sdsnew(const char *init) {
size_t initlen = (init == NULL) ? 0 : strlen(init);
return sdsnewlen(init, initlen);
}
sdsdup
拷贝sds
sds sdsdup(const sds s) {
return sdsnewlen(s, sdslen(s));
}
sdsfree
释放sds
void sdsfree(sds s) {
if (s == NULL) return;
zfree(s-sizeof(struct sdshdr));
}
zfree
的功能
释放内存并修改redis使用的内存大小。
sdsupdatelen
?废弃函数
根据代码我猜测是重新设置sds的大小
eg.
sds={10,0,"abc"/"abc\0defghi"}
==>
sds={3,7,"abc"}
void sdsupdatelen(sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
int reallen = strlen(s);
sh->free += (sh->len-reallen);
sh->len = reallen;
}
sdsclear
在不去真实释放sds空间的情况下,将sds变为空字符串。
void sdsclear(sds s) {
// 取出 sdshdr
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
sh->free += sh->len;
sh->len = 0;
sh->buf[0] = '\0';
}
sdsMakeRoomFor
sdsRemoveFreeSpace
真正的释放了惰性空间释放时的多余空间
sds sdsRemoveFreeSpace(sds s) {
struct sdshdr *sh;
sh = (void*) (s-(sizeof(struct sdshdr)));
// 进行内存重分配,让 buf 的长度仅仅足够保存字符串内容
// T = O(N)
sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1);
// 空余空间为 0
sh->free = 0;
return sh->buf;
}
sdsAllocSize
获得sds一共分配保存字符串的空间(len+free+'\0'
)
size_t sdsAllocSize(sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
return sizeof(*sh)+sh->len+sh->free+1;
}
sdsIncrLen
void sdsIncrLen(sds s, int incr) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
// 确保 sds 空间足够
assert(sh->free >= incr);
// 更新属性
sh->len += incr;
sh->free -= incr;
// 这个 assert 其实可以忽略
// 因为前一个 assert 已经确保 sh->free - incr >= 0 了
assert(sh->free >= 0);
// 放置新的结尾符号
s[sh->len] = '\0';
}