redis源码剖析-字符串

redis源码剖析-字符串

redis实现了自己的字符串结构。在文件sds.h/dsd.c中定义。redis中的字符串叫sds(simple dynamic string)。
sds实质是char*:
typedef char *sds;
sds通过sdsnewlen()函数来创建,sds sdsnewlen(const void *init, size_t initlen)。该函数内部会创建一个sdshdr的结构,返回值sds,即char *,该结构定义如下:
struct sdshdr
{
        int len;
        int free;
        char buf[];
};
其中len存储当前字符串的长度,free存储该结构体剩余可存储字节数,buf存储字符串值。sdsnewlen()函数在创建sdshdr后,会返回buf的地址(sdshdr->buf)。
sdsnewlen()函数创建了字符串,并返回字符串地址sds,要使用sdshdr中的len和free,则需要获取sdshdr结构体的地址。如何根据获得的sds得到sdshdr结构体的地址呢?
redis中参考了linux内核关于通用list(list_head)的实现机制,实现方法如下:
struct sdshdr *sh =  (void*) (sds-(sizeof(struct sdshdr)));
sds是返回的字符串地址,即sdshdr->buf,用sds的地址减去其在结构体中的偏移,即可得到sdshdr的地址。由于buf在sdshdr结构体的最后,所以其偏移就是sizeof(len)+sizeof(free),该偏移恰好是sizeof(struct sdshdr)。
如果buf在sdshdr中的位置是任意的,如何根据buf的地址获取sdshdr的地址呢?实现如下:
假设现在sdshdr声明如下:
struct sdshdr
{
        int len;
        char buf[];
        int free;       
};
则sdshdr地址如下获取:
int offset_buf = (int)((struct sdshdr *)0)->buf;      
struct sdshdr *sh =(struct sdshdr *)( (int)sdsbuf - offset_buf);  
其中sdsbuf是调用sdsnewlen()返回的buf地址。即 sds sdsbuf = sdsnewlen(...);
((struct sdshdr *)0)->buf 表示当结构体sdshdr在地址0时,buf相对于sdshdr首地址的偏移。

posted on 2012-07-03 00:59 MrRightLeft 阅读(1404) 评论(0)  编辑 收藏 引用 所属分类: redis


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年3月>
272812345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜