开始我们 redis 数据结构的第一旅程,简单动态字符串(simple dynamic string, SDS)从redis源码堆里独立出来,自立门户。
首先,从 redis 源代码文件夹 src 里拷贝出 sds.h 与 sds.c 两个文件。打开 sds.c 文件,能看到 include 头文件列表含有 sdsalloc.h 文件,sdsalloc.h 文件又包含了 zmalloc.h;
因此,我们也要引入atomicvar.h、 zmalloc.h 与 zmalloc.c 文件。然而,zmalloc.c 文件引入了 redis 中的 config.h、atomicvar.h 头文件。查看这些文件,我们发现它们代码量很多,此时我们用不着它们,所以我们先略过它们代码内容的细节,只管复制它们(统统复制到一个文件夹中)。
操作到这,目录文件下,总共有7个文件:sds.h、sds.c、zmalloc.h、zmalloc.c 、atomicvar.h、config.h、sdsalloc.h。接下来,写个makefile文件,内容如下:
make 与 makefile 文件应该对于非专业 C 开发者来说都会是陌生的,但它却是本系列不可少的知识点,想了解 make 请查看系列 --** 跟我一起写 Makefile**
CC := gcc
#CFLAGS := -w -std=gnu99 -ggdb -ffunction-sections # -w:关闭所有告警
CFLAGS := -g -I. $(CCFLAGS)
SRCS := $(wildcard *.c) # 当前目录下的所有的.c文件
OBJS := $(SRCS:.c=.o) # 将所有的.c文件名替换为.o
REDISLIB := libredis.a
all:$(REDISLIB) gccr
# ***************************************************************
# C compilations
zmalloc.o: zmalloc.c zmalloc.h
$(CC) $(CFLAGS) -c zmalloc.c
sds.o: sds.c sds.h
$(CC) $(CFLAGS) -c sds.c
$(REDISLIB):$(OBJS)
-rm -f $(REDISLIB)
ar cr $(REDISLIB) $(OBJS)
ranlib $(REDISLIB)
# ***************************************************************
# Entry to reconstruct the gccr script
gccr: makefile
@echo '#! /bin/csh -f' > gccr
@echo 'set INCLUDE =' `pwd` >> gccr
@echo 'set REDISLIB = $$INCLUDE/libredis.a' >> gccr
@echo 'set LIBRARIES = ($$REDISLIB)' >> gccr
@echo 'foreach x ($$*)' >> gccr
@echo ' if ("x$$x" == "x-c") then' >> gccr
@echo ' set LIBRARIES = ""' >> gccr
@echo ' break' >> gccr
@echo ' endif' >> gccr
@echo 'end' >> gccr
@echo 'gcc -g -I$$INCLUDE $$* $$LIBRARIES' >> gccr
@chmod a+x gccr
@echo '[gccr script created]'
clean:
rm -f *.o
rm -f $(BINS)
rm -f $(REDISLIB)
rm -f gccr
在当前目录下,执行命令:make
,主要会生成一个 shell 可执行文件 gccr 和另外一个 C 静态库文件 libredis.a 。libredis.a 静态库文件是我们能够实现单独去测试执行 redis 里的数据结构代码的关键。现让我们打开 gccr 这个文件:
#! /bin/csh -f
set INCLUDE = /www/redisResourceInAction/01-SDS
set REDISLIB = $INCLUDE/libredis.a
set LIBRARIES = ($REDISLIB)
foreach x ($*)
if ("x$x" == "x-c") then
set LIBRARIES = ""
break
endif
end
gcc -g -I$INCLUDE $* $LIBRARIES
细心的你也许注意到了第一句里有个 csh 。sh 之后另一个广为流传的 shell 是由柏克莱大学的 Bill Joy 设计的,这个 shell 的语法有点类似C语言,所以才得名为 C shell ,简称为 csh。如果你的 linux 环境不支持,请安装下。gccr文件内容就是纯 shell 命令,只要大概懂得一些 shell 命令就大概知道它在做什么。这个也会在后面博文进行详解。
为了能在shell命令行下,直接执行gccr , 执行:mv gccr /usr/local/bin
,把这个文件放入 /usr/local/bin 目录下。
ok! 至此,就大功告成,是不是感觉很简单。下面我们进行创建一些测试demo,来检查我们的动态字符串(SDS)
#include <stdio.h>
#include <string.h>
#include "sds.h"
int main() {
char *str = "hello";
sds sdsStr;
// 创建一个包含给定C字符串的SDS
sdsStr = sdsnew(str);
printf("sdsStr content: %s\n", sdsStr);
// 返回SDS的已使用空间字节数
size_t length = sdslen(sdsStr);
printf("sdsStr length: %d\n", length);
sds secondStr = "keep doing";
// 根据给定的初始化字符串 init 和字符串长度 initlen,创建一个新的 sds
sdsStr = sdsnewlen(secondStr, strlen(secondStr));
printf("new sdsStr content: %s\n", sdsStr);
length = sdslen(sdsStr);
printf("new sdsStr length: %d\n", length);
//create empty string
sds emptyStr = sdsempty();
printf("This is empty string: %s\n", emptyStr);
//dumplicate a string
sds dupStr = sdsdup(sdsStr);
printf("dumplicate of sdsStr: %s\n", dupStr);
return 0;
}
在此文件目录下,执行:gccr demo_1.c -o demo_1
,一切正常的情况下,再执行:./demo_1
如果能得到上图结果,那么你redis数据结构库就顺利生成了,且能正常编译代码。到此我们便打开探索 redis 源码之门。
刚开始写博客,很是不专业,感觉思维跳跃大,很难让读者知道所有的操作步骤,还请多多包涵。
附上 github源码,如有不懂的地方请留言。