zmalloc.c文件中主要是内存分配一些操作,其中主要是对C语言内存分配函数进行了一定封装,加上了一些其他的功能(如统计,异常处理等等)。总体来说还是十分简单的
zmalloc&zcalloc
在redis中,zmalloc函数是对系统malloc的一种封装。增加了内存统计的功能
以下是zmalloc函数的源代码
至于zrealloc,跟zmalloc十分类似,在此就不赘言了。
void *zmalloc(size_t size) {
void *ptr = malloc(size+PREFIX_SIZE);
//如果分配失败的话,则使用异常处理函数
if (!ptr) zmalloc_oom_handler(size);
//申请完毕后,将会做内存统计。
#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_alloc(zmalloc_size(ptr));
return ptr;
#else
*((size_t*)ptr) = size;
update_zmalloc_stat_alloc(size+PREFIX_SIZE);
return (char*)ptr+PREFIX_SIZE;
#endif
}
//附
//这里宏函数先对__n变量进行了对于long的内存对齐,后使用原子操作增加used_memory
#define update_zmalloc_stat_alloc(__n) do { \
size_t _n = (__n); \
if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
atomicIncr(used_memory,__n); \
} while(0)
//同理,这个是一旦free内存后,继续更新的统计的操作,同样加入了对其。
#define update_zmalloc_stat_free(__n) do { \
size_t _n = (__n); \
if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
atomicDecr(used_memory,__n); \
} while(0)
zrealloc
//realloc函数
void *zrealloc(void *ptr, size_t size) {
#ifndef HAVE_MALLOC_SIZE
void *realptr;
#endif
size_t oldsize;
void *newptr;
//如果指针为NULL的话,那么realloc相当于alloc。所以直接调用zmalloc函数即可
if (ptr == NULL) return zmalloc(size);
//如果定义了HAVE_MALLOC_SIZE宏的话,就先将以前分配的内存直接清零,然后直接重新分配
#ifdef HAVE_MALLOC_SIZE
oldsize = zmalloc_size(ptr);
newptr = realloc(ptr,size);
if (!newptr) zmalloc_oom_handler(size);
update_zmalloc_stat_free(oldsize); //减去oldsize
update_zmalloc_stat_alloc(zmalloc_size(newptr)); //加入new的size
return newptr;
//如果不是的话,就先找到内存的起始点,然后重新分配
#else
realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr);
newptr = realloc(realptr,size+PREFIX_SIZE);
if (!newptr) zmalloc_oom_handler(size);
*((size_t*)newptr) = size;
update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
update_zmalloc_stat_alloc(size+PREFIX_SIZE);
return (char*)newptr+PREFIX_SIZE;
#endif
}
//free函数,本质上就是调用了free函数,同时更新了内存统计数据
void *zrealloc(void *ptr, size_t size) {
#ifndef HAVE_MALLOC_SIZE
void *realptr;
#endif
size_t oldsize;
void *newptr;
if (ptr == NULL) return zmalloc(size);
#ifdef HAVE_MALLOC_SIZE
oldsize = zmalloc_size(ptr);
newptr = realloc(ptr,size);
if (!newptr) zmalloc_oom_handler(size);
update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(zmalloc_size(newptr));
return newptr;
#else
realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr);
newptr = realloc(realptr,size+PREFIX_SIZE);
if (!newptr) zmalloc_oom_handler(size);
*((size_t*)newptr) = size;
update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
update_zmalloc_stat_alloc(size+PREFIX_SIZE);
return (char*)newptr+PREFIX_SIZE;
#endif
}