内容
- redis中的内存分配api
- redis中的原子操作api
源代码
Redis中的内存分配和原子操作
代码构建
1
2
|
cp /home/vagrant/github/server_installer/servers/redis/redis-6.2/src/zmalloc.* .
cp /home/vagrant/github/server_installer/servers/redis/redis-6.2/src/atomicvar.h .
|
zmalloc.c中引用了config.h, 删除掉
新建server.c, 内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include "stdio.h"
#include "atomicvar.h"
#include "zmalloc.h"
int main(int argc, char **argv){
redisAtomic long long i = 10;
atomicIncr(i, 3);
printf("hello %lld\n",i);
char *p;
p = zmalloc(10);
p = "hello";
printf("hello %s\n",p);
int accurate;
accurate = 10;
#ifdef REDIS_TEST
zmalloc_test( argc,argv,accurate );
#endif
return 0;
}
|
新建Makefile
1
2
3
4
5
6
7
8
9
10
11
|
server : zmalloc.o server.o
$(CC) -o $@ $^
%.o: %.c
$(CC) -DREDIS_TEST=1 -MMD -o $@ -c $<
.PHONY: clean
clean:
rm -rf *.o *.d server
|
再看一下zmalloc_test
的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#ifdef REDIS_TEST
#define UNUSED(x) ((void)(x))
int zmalloc_test(int argc, char **argv, int accurate) {
void *ptr;
UNUSED(argc);
UNUSED(argv);
UNUSED(accurate);
printf("Malloc prefix size: %d\n", (int) PREFIX_SIZE);
printf("Initial used memory: %zu\n", zmalloc_used_memory());
ptr = zmalloc(123);
printf("Allocated 123 bytes; used: %zu\n", zmalloc_used_memory());
ptr = zrealloc(ptr, 456);
printf("Reallocated to 456 bytes; used: %zu\n", zmalloc_used_memory());
zfree(ptr);
printf("Freed pointer; used: %zu\n", zmalloc_used_memory());
return 0;
}
#endif
|
输出
1
2
3
4
5
6
7
|
hello 13
hello hello
Malloc prefix size: 0
Initial used memory: 24
Allocated 123 bytes; used: 160
Reallocated to 456 bytes; used: 480
Freed pointer; used: 24
|
解释
对于zmalloc函数,可以直接对应到c标准库里的malloc, realoc, free函数,redis会根据不同的实现调用不同的内存分配库,以实现更好的性能以及更多的功能。因为redis中已经写好测试了,我们就直接调用了。这里面用到了预编译。正常的编译不会把测试函数编译进redis server中的。在编译多c文件中,没有制定如何生成*.o文件。当用上篇文章中的Makefile编译时会提升找不到zmalloc_test
的实现。通过查看redis的Makefile, 发现了
1
2
|
%.o: %.c
$(CC) -DREDIS_TEST=1 -MMD -o $@ -c $<
|
里面的MMD是什么含义呢,下面参考文章有详细的解释,这里总结一下
. M 依赖的文件
. MM 去除#include
引用的依赖后的依赖
. D 是生成依赖文件,后缀为.d, 所以有MD 和MMD,这里用的MMD
linux下原子操作是C11中的封装。
输出为:zmalloc.o: zmalloc.c zmalloc.h atomicvar.h
redis zmalloc & atomic api
- size_t zmalloc_used_memory(void) – 动态分配内存
- void *zmalloc(size_t size)–分配内存
- void *zrealloc(void *ptr, size_t size)– 重新分配内存
- void zfree(void *ptr) – 释放内存
- atomicIncr(var,count) – 原子加
- atomicGetIncr(var,oldvalue_var,count) – Get and increment the atomic counter
- atomicDecr(var,count) – 原子减
- atomicGet(var,dstvar) – 原子取
- atomicSet(var,value) – 原子设置数
- atomicGetWithSync(var,value) – 原子取, 不成功一直循环
- atomicSetWithSync(var,value) – 原子设置, 不成功一直循环
参考
MMD含义