由Cache引发的关于Malloc函数的思考

本文探讨了计算机内存管理中Malloc函数的使用,特别是在初始化Cache缓存器时遇到的问题。作者通过实验发现,尽管Cache的每一组在内存中是连续的,但组内的行却是通过指针指向非连续的地址。这揭示了Malloc在分配内存时的映射关系,即一维数组存储的是指向二维数组位置的指针,而非连续的内存空间。这一发现加深了对内存分配机制的理解。
摘要由CSDN通过智能技术生成

关于Malloc函数的一些理解

思考缘由

在计算机系统的实验6中,需要我们根据输入的要求去init一个Cache缓存器。代码如下:
initCache
其中注释的内容是我后续为了理解mallo添加语句。
这个init是这样子实现的:我们知道一个Cache中有多个组,每个组中又有多行缓存块。在我们这个init函数中,S是组的数量,E是行的数量。我们先malloc initCache的组数,然后再对每一组malloc 行数。用二维数组来理解的话就是我们先malloc行数,再malloc列数。
这里就有一个问题,由于cache_set_t的大小根据要求是给定的:
cache的定义
当我malloc组数之后,我们又如何能够对每一组去扩充他的行数?
所以将cache中的信息都打印出来:
打印信息
我们发现Cache中的每一组都是连续的,161400,161408,161410。而每一组的每一行的地址是从164120开始,也就是说后续我们新扩增的Cache行是在后面增加的而不是我一开始想象中的类似矩阵一样连续的。


在写这个blog时,我忽然发现:Cache中的一维数组存的是一个指针,也就是这个指针指向了二维数组的位置,所以malloc才会是这样子的一个映射关系,而不像通常数组那样是连续的地址。

lvgl库中的 `lv_img_cache_invalidate_src` 函数会清除图片缓存,当需要重新加载同一张图片时,会导致图片加载变慢。这个问题主要是由于每次重新加载图片时,都需要从文件系统或网络中读取图片数据,而这个过程会消耗一定的时间。 为了解决这个问题,我们可以通过以下两种方式来优化图片加载速度: 1. 使用内存缓存 使用内存缓存可以避免每次重新加载图片时都需要从文件系统或网络中读取图片数据的问题。我们可以在程序启动时将所有需要使用的图片数据预先加载到内存中,并将其保存在一个内存缓存中。当需要加载图片时,我们可以先从内存缓存中查找是否有对应的图片数据,如果有则直接使用内存中的数据,否则再从文件系统或网络中加载数据并保存到内存缓存中。 2. 延迟加载 延迟加载是指在需要使用图片时才进行加载,而不是在程序启动时就进行加载。这样可以避免一些不必要的加载操作,从而提高图片加载的速度。我们可以在程序中使用一个标志位来表示某张图片是否已经被加载过,如果没有被加载过则在需要使用时进行加载。 下面是一个使用内存缓存的示例代码: ```c #include "lvgl/lvgl.h" #include <stdlib.h> #include <string.h> // 图片缓存结构体 typedef struct { const char *src; // 图片路径 void *data; // 图片数据 uint32_t size; // 图片数据大小 } img_cache_t; // 内存缓存数组 static img_cache_t *img_cache = NULL; static uint32_t img_cache_size = 0; // 图片缓存初始化函数,将需要使用的图片数据预先加载到内存中 void img_cache_init(void) { // 预先加载图片数据到内存中 img_cache_t cache[] = { {"path/to/image1.png", NULL, 0}, {"path/to/image2.png", NULL, 0}, {"path/to/image3.png", NULL, 0}, // ... }; img_cache_size = sizeof(cache) / sizeof(cache[0]); // 申请内存缓存空间 img_cache = (img_cache_t *)malloc(img_cache_size * sizeof(img_cache_t)); if (img_cache == NULL) { return; } // 将图片数据保存到内存缓存中 for (int i = 0; i < img_cache_size; i++) { FILE *fp = fopen(cache[i].src, "rb"); if (fp == NULL) { continue; } fseek(fp, 0, SEEK_END); cache[i].size = ftell(fp); fseek(fp, 0, SEEK_SET); cache[i].data = malloc(cache[i].size); if (cache[i].data == NULL) { fclose(fp); continue; } fread(cache[i].data, cache[i].size, 1, fp); fclose(fp); img_cache[i] = cache[i]; } } // 图片加载函数,先从内存缓存中查找,如果没有则从文件系统或网络中加载 lv_res_t img_load(lv_obj_t *img, const char *src) { // 先从内存缓存中查找 for (int i = 0; i < img_cache_size; i++) { if (strcmp(src, img_cache[i].src) == 0) { lv_img_set_data(img, img_cache[i].data, img_cache[i].size); return LV_RES_OK; } } // 如果内存缓存中没有,则从文件系统或网络中加载 FILE *fp = fopen(src, "rb"); if (fp == NULL) { return LV_RES_INV; } fseek(fp, 0, SEEK_END); uint32_t size = ftell(fp); fseek(fp, 0, SEEK_SET); void *data = malloc(size); if (data == NULL) { fclose(fp); return LV_RES_INV; } fread(data, size, 1, fp); fclose(fp); // 将加载的图片数据保存到内存缓存中 img_cache_t cache = {src, data, size}; img_cache = (img_cache_t *)realloc(img_cache, (img_cache_size + 1) * sizeof(img_cache_t)); if (img_cache == NULL) { free(data); return LV_RES_INV; } img_cache[img_cache_size++] = cache; // 设置图片数据 lv_img_set_data(img, data, size); return LV_RES_OK; } ``` 在上面的示例代码中,我们先使用 `img_cache_init` 函数将需要使用的图片数据预先加载到内存中,并保存在一个名为 `img_cache` 的内存缓存中。在图片加载函数 `img_load` 中,我们先从内存缓存中查找是否有对应的图片数据,如果有则直接使用内存中的数据,否则再从文件系统或网络中加载数据并保存到内存缓存中。 使用内存缓存可以有效地避免每次重新加载图片时都需要从文件系统或网络中读取图片数据的问题,从而提高图片加载的速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值