博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis代码阅读之Hacking Strings
阅读量:5749 次
发布时间:2019-06-18

本文共 2648 字,大约阅读时间需要 8 分钟。

Hacking Strings

The implementation of Redis strings is contained in sds.c ( sds stands for Simple Dynamic Strings ).

The C structure sdshdr declared in sds.h represents a Redis string:

struct sdshdr {    long len;    long free;    char buf[];};

The buf character array stores the actual string.

The len field stores the length of buf. This makes obtaining the length of a Redis string an O(1) operation.
The free field stores the number of additional bytes available for use.
Together the len and free field can be thought of as holding the metadata of the buf character array.

Creating Redis Strings

A new data type named sds is defined in sds.h to be a synonymn for a character pointer:

typedef char *sds;

sdsnewlen function defined in sds.c creates a new Redis String: 

sds sdsnewlen(const void *init, size_t initlen) {    struct sdshdr *sh;    sh = zmalloc(sizeof(struct sdshdr)+initlen+1);#ifdef SDS_ABORT_ON_OOM    if (sh == NULL) sdsOomAbort();#else    if (sh == NULL) return NULL;#endif    sh->len = initlen;    sh->free = 0;    if (initlen) {        if (init) memcpy(sh->buf, init, initlen);        else memset(sh->buf,0,initlen);    }    sh->buf[initlen] = '\0';    return (char*)sh->buf;}

Remember a Redis string is a variable of type struct sdshdr. But sdsnewlen returns a character pointer!!

That's a trick and needs some explanation.
Suppose I create a Redis string using sdsnewlen like below:

sdsnewlen("redis", 5);

This creates a new variable of type struct sdshdr allocating memory for len and free fields as well as for the buf character array.

sh = zmalloc(sizeof(struct sdshdr)+initlen+1); // initlen is length of init argument.

After sdsnewlen succesfully creates a Redis string the result is something like:

-----------|5|0|redis|-----------^   ^sh  sh->buf

sdsnewlen returns sh->buf to the caller.

What do you do if you need to free the Redis string pointed by sh?
You want the pointer sh but you only have the pointer sh->buf.
Can you get the pointer sh from sh->buf?
Yes. Pointer arithmetic. Notice from the above ASCII art that if you subtract the size of two longs from sh->buf you get the pointer sh
The sizeof two longs happens to be the size of struct sdshdr.
Look at sdslen function and see this trick at work:

size_t sdslen(const sds s) {    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));    return sh->len;}

Knowing this trick you could easily go through the rest of the functions in sds.c.

The Redis string implementation is hidden behind an interface that accepts only character pointers. The users of Redis strings need not care about how its implemented and treat Redis strings as a character pointer.

转载地址:http://anhzx.baihongyu.com/

你可能感兴趣的文章
CCNA实验之:网络地址转换(NAT)实验
查看>>
计算机网络原理笔记-停止等待协议
查看>>
确定当前记录和下一条记录之间相差的天数
查看>>
sql语句返回主键SCOPE_IDENTITY()
查看>>
机器学习开源项目精选TOP30
查看>>
/etc/resolv.conf文件详解
查看>>
【转】VC的MFC中重绘函数的使用总结(整理)
查看>>
JQuery日记_5.13 Sizzle选择器(六)选择器的效率
查看>>
oracle查看经常使用的系统信息
查看>>
Django_4_视图
查看>>
Linux的netstat命令使用
查看>>
lvm讲解,磁盘故障小案例
查看>>
大快网站:如何选择正确的hadoop版本
查看>>
经过这5大阶段,你离Java程序员就不远了!
查看>>
IntelliJ IDEA 连接数据库详细过程
查看>>
thymeleaf 学习笔记-基础篇
查看>>
PHP-X开发扩展
查看>>
android学习笔记——onSaveInstanceState的使用
查看>>
工作中如何做好技术积累
查看>>
怎么用sysLinux做U盘双PE+DOS??
查看>>