0
点赞
收藏
分享

微信扫一扫

Redis3.0源码学习笔记(一)——zmalloc.c文件

邯唐情感 2022-04-13 阅读 21
redisc语言

持续更新中…

zmalloc.c源码阅读笔记

源码内容

主要函数功能简述
zmalloc()分配内存,但不初始化
zfree()清理zmalloc()分配的内存
zcalloc()分配内存,并初始化为0
zrelloc()重新分配内存
zstrdup()字符串复制
主要宏功能简述
#define PREFIX_SIZE (sizeof(size_t))在Linux中sizeof(size_t)其值是8个字节
#define update_zmalloc_stat_alloc(__n)字节对齐、判断线程环境是否安全,维护全局已分配内存数量的增加
#define update_zmalloc_stat_free(__n)字节对齐、判断线程环境是否安全,维护全局已分配内存数量的减少
其他函数功能简述
zmalloc_default_oom()用于报错
其他宏功能简述
#define update_zmalloc_stat_add(__n)使用线程安全方式为系统已分配内存(全局变量)增加n
#define update_zmalloc_stat_sub(__n)使用线程安全方式为系统已分配内存(全局变量)减少n

宏源码分析

update_zmalloc_stat_alloc() & update_zmalloc_stat_free()

do{
	...
}while(0)
//这种代码风格的作用可以参考如下博客

链接:do{…}while(0)的意义和用法

#define update_zmalloc_stat_alloc(__n) do { \
    size_t _n = (__n); \
    //用于字节对齐
    //等价于  if(_n&7) _n += 8 - (_n&7);
    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \ 
    //检查线程环境是否安全
    if (zmalloc_thread_safe) { \
        update_zmalloc_stat_add(_n); \
    } else { \
    	//安全时使用
        used_memory += _n; \
    } \
} while(0)
#define update_zmalloc_stat_free(__n) do { \
    size_t _n = (__n); \
    //用于字节对齐
    //等价于  if(_n&7) _n += 8 - (_n&7);
    if (_n&(sizeof(long)-1)) _n += sizeof(long)-(_n&(sizeof(long)-1)); \
    if (zmalloc_thread_safe) { \
        update_zmalloc_stat_sub(_n); \
    } else { \
       	//安全时使用
        used_memory -= _n; \
    } \
} while(0)

update_zmalloc_stat_add() & update_zmalloc_stat_sub()

确保线程安全,加了个线程锁。

#define update_zmalloc_stat_add(__n) do { \
    pthread_mutex_lock(&used_memory_mutex); \
    used_memory += (__n); \
    pthread_mutex_unlock(&used_memory_mutex); \
} while(0)
#define update_zmalloc_stat_sub(__n) do { \
    pthread_mutex_lock(&used_memory_mutex); \
    used_memory -= (__n); \
    pthread_mutex_unlock(&used_memory_mutex); \
} while(0)

函数源码分析

zmalloc()

void *zmalloc(size_t size) {
    void *ptr = malloc(size+PREFIX_SIZE);//分配了一段8+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
}

zcalloc()

void *zcalloc(size_t size) {
    void *ptr = calloc(1, size+PREFIX_SIZE);//有效部分唯一区别于zmalloc()的语句
	/*
	void *calloc(size_t nmemb, size_t size);
	分配nmemb*size字节的内存并初始化为0
	*/
    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
}

zrealloc()

给ptr开始的内存空间重新分配size大小的空间,若失败就在其他位置新建一块大小为size字节的空间,并将原先的数据复制过去。原内存会

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);
    //zrealloc()实际上调用了realloc()函数
    newptr = realloc(realptr,size+PREFIX_SIZE);
    if (!newptr) zmalloc_oom_handler(size);

    *((size_t*)newptr) = size;
    //对全局变量做修改,减去之前分配的字节数,加上新分配的字节数
    update_zmalloc_stat_free(oldsize);
    update_zmalloc_stat_alloc(size);
    return (char*)newptr+PREFIX_SIZE;
#endif
}

zfree()

void zfree(void *ptr) {
#ifndef HAVE_MALLOC_SIZE
    void *realptr;
    size_t oldsize;
#endif

    if (ptr == NULL) return;

/*****************无效部分*****************/
#ifdef HAVE_MALLOC_SIZE
    update_zmalloc_stat_free(zmalloc_size(ptr));
    free(ptr);
/*****************无效部分*****************/

#else
	//获取需要释放的字节数
    realptr = (char*)ptr-PREFIX_SIZE;
    oldsize = *((size_t*)realptr);
    
    //对全局变量做修改,减去需要释放的字节数
    update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
    free(realptr);
#endif
}

zstrdup()

char *zstrdup(const char *s) {
	//获取源字符串长度,strlen()不统计'\0',故+1
    size_t l = strlen(s)+1;
	
	//调用zmalloc分配空间
    char *p = zmalloc(l);

	//void *memcpy(void *dest, const void *src, size_t n);
    memcpy(p,s,l);
    return p;
}
举报

相关推荐

0 条评论