一种简单实用的内存管理实现方法

本文介绍了分块式内存管理的原理,包括内存池和内存管理表的结构,以及如何通过malloc和free函数进行内存的分配和释放。当malloc申请内存时,从内存池中寻找连续的空闲块并标记,而free则通过查找内存管理表释放内存并清零标记。提供的源码已在Windows平台测试通过。
摘要由CSDN通过智能技术生成

一.原理解说

内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如 何高效,快速的分配,并且在适当的时候释放和回收内存资源。内存管理的实现方法有很多种, 他们其实最终都是要实现 2 个函数:malloc 和 free;malloc 函数用于内存申请,free 函数用于内存释放。

我们介绍一种比较简单的办法来实现:分块式内存管理。下面我们介绍一下该方法的实现原理。

从上图可以看出,分块式内存管理由内存池和内存管理表两部分组成。内存池被等分为 n 块,对应的内存管理表,大小也为 n,内存管理表的每一个项对应内存池的一块内存。 内存管理表的项值代表的意义为:当该项值为 0 的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。 比如某项值为 10,那么说明包括本项对应的内存块在内,总共分配了 10 个内存块给外部的某个指针。

分配原理

当指针 p 调用 malloc 申请内存的时候,先判断 p 要分配的内存块数(m),然后从第 n 项开始,向下查找,直到找到 m 块连续的空内存块(即对应内存管理表项为 0),然后将这 m 个内 存管理表项的值都设置为 m(标记被占用),最后,把最后的这个空内存块的地址返回指针 p, 完成一次分配。注意,如果当内存不够的时候(找到最后也没找到连续的 m 块空闲内存),则返回 NULL 给 p,表示分配失败。

释放原理

当 p 申请的内存用完,需要释放的时候,调用 free 函数实现。free 函数先判断 p 指向的内 存地址所对应的内存块,然后找到对应的内存管理表项目,得到 p 所占用的内存块数目 m(内 存管理表项目的值就是所分配内存块的数目),将这 m 个内存管理表项目的值都清零,标记释放,完成一次内存释放。

说明

本文章的内存管理设计思想完全参考了正点原子的资料,设计方法基本一致,唯一不同的是后续提供的实现源码是本人根据上述设计思路实现的,没有使用正点原子的代码,可移植到任何平台使用,特此说明。

二.源码

源码在windows平台编译测试过,功能完全ok。

#include<stdio.h>
#include <string.h>

#define MAX_LEN   1024*10  //内存池大小
#define BLOCK_SIZE 128     //内存块大小
unsigned char mem_buff[MAX_LEN] = {0};
typedef struct
{
    unsigned char index[MAX_LEN/BLOCK_SIZE];
}_mem_tab;
_mem_tab mem_tab;

unsigned char *my_malloc(int buf_size)
{
    int i = 0;
    int j = 0;
    int flag = 0;
    int record = 0;     //记录当前分配内存管理表项的位置
    int block_num = 0;  //需要分配内存块的数量
    block_num = buf_size%BLOCK_SIZE ? buf_size/BLOCK_SIZE+1 : buf_size/BLOCK_SIZE;
    printf("block_num: %d \r\n",block_num);
    if(block_num > MAX_LEN/BLOCK_SIZE){//申请内存大小超出内存池范围,退出
        return NULL;
    }
    while(i < MAX_LEN/BLOCK_SIZE){
        if(mem_tab.index[i] == 0){
            if(flag == 0){
                flag = 1;
                record = i;
            }
            j++;
            if(j >= block_num){
                memset(mem_tab.index+record,block_num,block_num);
                return (mem_buff+record*BLOCK_SIZE);
            }
        }else{
            flag = 0;
            j = 0;
        }
        i++;
    }
    return NULL;
}

void my_free(unsigned char *buf)
{
    int num = 0;
    if(buf == NULL){
        printf("NULL buffer!!!\r\n");
        return;
    }
    //判断释放的缓存地址是否在内存池范围内
    if(*(&buf) < *(&mem_buff) || *(&buf) > *(&mem_buff) + MAX_LEN){
        printf("error buffer!!!\r\n");
        return;
    }
    num = (*(&buf) - *(&mem_buff))/BLOCK_SIZE;
    /*
    printf("buff addr %d\r\n",*(&buf));
    printf("buff addr %d\r\n",*(&mem_buff));
    printf("size %d \r\n",*(&buf) - *(&mem_buff));
    printf("num %d \r\n",mem_tab.index[num]);
    */
    //清除管理表项标记
    memset(mem_tab.index+num,0,mem_tab.index[num]);
    //清除回收回来的内存池内容
    memset(buf,0,num*BLOCK_SIZE);
    //将内存指针指向空
    buf = NULL;
}

void main(void)
{
    unsigned char test[] = "this is a test project !";
    unsigned char *buf;
    buf = my_malloc(sizeof(test));
    if(buf != NULL){
        memcpy(buf,test,sizeof(test));
        printf("%s",buf);
        my_free(buf);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值