redis 0.091 源码分析之zmalloc模块

本文以redis官网能下载的最早版本(0.091)源码为基础,官网下载地址:https://download.redis.io/releases/redis-0.091.tar.gz

redis中的zmalloc主要是对c标准库中的内存操作函数(malloc,free,realloc)进行封装,加入used_memory记录占用内存大小。

每个内存块头部加入一个size_t记录上层申请内存的大小(不包括头部size_t占用空间),使用size_t是为了更好的兼容性,满足不同系统记录内存大小,最后把申请到内存的首地址偏移size_t占用的字节返回上层使用。
在这里插入图片描述

/* zmalloc - total amount of allocated memory aware version of malloc()
	...
 */

#include <stdlib.h>
#include <string.h>

// 静态变量记录使用内存大小,单位字节
static size_t used_memory = 0;

// 申请内存,对于malloc
void *zmalloc(size_t size) {
	// 调用malloc申请内存,大小加上sizeof(size_t)
    void *ptr = malloc(size+sizeof(size_t));
	// 把size数值存入刚申请到的内存头部
    *((size_t*)ptr) = size;
    // 更新使用内存大小
    used_memory += size+sizeof(size_t);
   	// 申请到的首地址偏移sizeof(size_t)个字节再返回上一层
   	// *注:因为指针加减法要对指针进行sizeof(ptr)计算后确定偏移量,这里把ptr转为char*,sizeof(char *)等于1个字节,这样就和sizeof(size_t)返回的字节数相对应
    return (char*)ptr+sizeof(size_t);
}

// 重新分配内存,对应realloc
void *zrealloc(void *ptr, size_t size) {
	// 真实内存首地址
    void *realptr;
    // 原大小
    size_t oldsize;
    // 新的真实内存首地址
    void *newptr;
	// 如果ptr为空则直接申请新的内存返回
    if (ptr == NULL) return zmalloc(size);
    // 上层的首地址减去sizeof(size_t)个字节,得到真实申请到的内存首地址,至于为什么转为char*请看zmallo的注释
    realptr = (char*)ptr-sizeof(size_t);
    // 首地址的内存数据就是原来申请内存大小
    oldsize = *((size_t*)realptr);
    // 调用realloc重新分配内存,根据realloc特性newptr不一定等于realptr
    newptr = realloc(realptr,size+sizeof(size_t));
    // 申请不到返回NULL代表失败
    if (!newptr) return NULL;
	// 把新的size复制到新申请的内存的首地址
    *((size_t*)newptr) = size;
    // 更新使用内存大小
    used_memory -= oldsize;
    used_memory += size;
    // 和zmalloc一样,首地址偏移后再返回上层
    return (char*)newptr+sizeof(size_t);
}

// 释放内存,对应free
void zfree(void *ptr) {
	// 真实内存首地址
    void *realptr;
    // 原内存大小
    size_t oldsize;
	// 如果为空指针则直接返回
    if (ptr == NULL) return;
    // 计算真实内存首地址,和zrealloc一样
    realptr = (char*)ptr-sizeof(size_t);
    // 读取真实内存首地址数据
    oldsize = *((size_t*)realptr);
    // 更新内存,要加上sizeof(size_t)才是真实申请内存的大小
    used_memory -= oldsize+sizeof(size_t);
    // 释放内存
    free(realptr);
}

// 字符串复制方法
char *zstrdup(const char *s) {
    size_t l = strlen(s)+1;
    char *p = zmalloc(l);

    memcpy(p,s,l);
    return p;
}

// 返回使用内存大小
size_t zmalloc_used_memory(void) {
    return used_memory;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值