• 单片机内存管理


    源码说明

    源码包含memory.h 和 memory.c 两个文件(嵌入式C/C++代码的“标配”),其源码中包含重要的注释。

    memory.h文件包含结构体等定义,函数API申明等;

    memory.c文件是实现内存管理相关API函数的原型。

    memory.h

    头文件是相关的定义和申请:

    1. #ifndef __MEMORY_H__
    2. #define __MEMORY_H__
    3. #include "stdio.h"
    4. #include "string.h"
    5. #include "includes.h"
    6. //用户使用
    7. typedef struct
    8. {
    9. void *addr; //申请到的内存的起始地址
    10. uint32_t size; //申请到的内存的大小,按照块大小分配,大于等于申请大小
    11. uint16_t tb; //申请表序号,申请内存时分配,释放内存时使用,用户不使用
    12. }DMEM;
    13. //若返回空,则申请失败
    14. DMEM *DynMemGet(uint32_t size);
    15. void DynMemPut(DMEM *pDmem);
    16. #endif //__M

    这里的代码比较简单,也是常规的写法,重点是要理解结构体成员的含义。

    memory.c

    源文件主要就是实现内存管理的函数,源码比较多,这里才分为三部分。

    1.相关的定义

     
    
    1. #include "memory.h"

    2. #define DMEM_BLOCK_SIZE 256 //内存块大小为128字节

    3. #define DMEM_BLOCK_NUM 20 //内存块个数为40个

    4. #define DMEM_TOTAL_SIZE (DMEM_BLOCK_SIZE*DMEM_BLOCK_NUM) //内存总大小

    5. static uint8_t DMEMORY[DMEM_TOTAL_SIZE];

    6. static DMEM_STATE DMEMS = {0};

    7. typedef enum

    8. {

    9. DMEM_FREE = 0,

    10. DMEM_USED = 1,

    11. }DMEM_USED_ITEM;

    12. typedef struct

    13. {

    14. DMEM_USED_ITEM used; //使用状态

    15. uint16_t blk_s; //起始块序号

    16. uint16_t blk_num; //块个数

    17. }DMEM_APPLY;

    18. typedef struct

    19. {

    20. DMEM_USED_ITEM tb_blk[DMEM_BLOCK_NUM];

    21. DMEM tb_user[DMEM_BLOCK_NUM]; //用户申请内存信息

    22. DMEM_APPLY tb_apply[DMEM_BLOCK_NUM]; //系统分配内存信息

    23. uint16_t apply_num; //内存申请表占用数目

    24. uint16_t blk_num; //内存块占用数目

    25. }DMEM_STATE;

    2.内存分配函数DynMemGet

     
    
    1. DMEM *DynMemGet(uint32_t size)

    2. {

    3. uint16_t loop = 0;

    4. uint16_t find = 0;

    5. uint16_t blk_num_want = 0;

    6. DMEM * user = NULL;

    7. DMEM_APPLY *apply = NULL;

    8. //申请内存大小不能为0

    9. if(size == 0) { return NULL; }

    10. //申请内存不可超过总内存大小

    11. if(size > DMEM_TOTAL_SIZE) { return NULL; }

    12. //申请内存不可超过剩余内存大小

    13. if(size > (DMEM_BLOCK_NUM - DMEMS.blk_num) * DMEM_BLOCK_SIZE) { return NULL; }

    14. //申请表必须有空余

    15. if(DMEMS.apply_num >= DMEM_BLOCK_NUM) { return NULL; }

    16. //计算所需连续块的个数

    17. blk_num_want = (size + DMEM_BLOCK_SIZE - 1) / DMEM_BLOCK_SIZE;

    18. //寻找申请表

    19. for(loop = 0; loop < DMEM_BLOCK_NUM; loop++)

    20. {

    21. if(DMEMS.tb_apply[loop].used == DMEM_FREE)

    22. {

    23. apply = &DMEMS.tb_apply[loop]; //申请表已找到

    24. user = &DMEMS.tb_user[loop]; //用户表对应找到

    25. user->tb = loop; //申请表编号记录

    26. user->size = blk_num_want * DMEM_BLOCK_SIZE; //分配大小计算

    27. break;

    28. }

    29. }

    30. //没有找到可用申请表,理论上是不会出现此现象的,申请表剩余已在上面校验

    31. if(loop == DMEM_BLOCK_NUM) { return NULL; }

    32. //寻找连续内存块

    33. for(loop = 0; loop < DMEM_BLOCK_NUM; loop++)

    34. {

    35. if(DMEMS.tb_blk[loop] == DMEM_FREE)

    36. {//找到第一个空闲内存块

    37. for(find = 1; (find < blk_num_want) && (loop + find < DMEM_BLOCK_NUM); find ++)

    38. {//找到下一个空闲内存块

    39. if(DMEMS.tb_blk[loop + find] != DMEM_FREE)

    40. {//发现已使用内存块

    41. break;

    42. }

    43. }

    44. if(find >= blk_num_want)

    45. {//寻找到的空闲内存块数目已经够用

    46. user->addr = DMEMORY + loop * DMEM_BLOCK_SIZE; //计算申请到的内存的地址

    47. apply->blk_s = loop; //记录申请到的内存块首序号

    48. apply->blk_num = blk_num_want; //记录申请到的内存块数目

    49. for(find = 0 ; find < apply->blk_num; find++)

    50. {

    51. DMEMS.tb_blk[loop + find] = DMEM_USED;

    52. }

    53. apply->used = DMEM_USED; //标记申请表已使用

    54. DMEMS.apply_num += 1;

    55. DMEMS.blk_num += blk_num_want;

    56. return user;

    57. }

    58. else

    59. {//寻找到的空闲内存块不够用,从下一个开始找

    60. loop += find;

    61. }

    62. }

    63. }

    64. //搜索整个内存块,未找到大小适合的空间

    65. return NULL;

    66. }

    3.内存释放函数DynMemPut

    1. void DynMemPut(DMEM *user)

    2. {

    3. uint16_t loop = 0;

    4. //若参数为空,直接返回

    5. if(NULL == user) { return; }

    6. //释放内存空间

    7. for(loop = DMEMS.tb_apply[user->tb].blk_s; loop < DMEMS.tb_apply[user->tb].blk_s + DMEMS.tb_apply[user->tb].blk_num; loop++)

    8. {

    9. DMEMS.tb_blk[loop] = DMEM_FREE;

    10. DMEMS.blk_num -= 1;

    11. }

    12. //释放申请表

    13. DMEMS.tb_apply[user->tb].used = DMEM_FREE;

    14. DMEMS.apply_num -= 1;

    15. }

  • 相关阅读:
    lambda表达式
    c++多线程学习11 packaged_task异步调用函数打包
    水库大坝安全监测方案,筑牢水库安全防线!
    ResNet网络详解及其PyTorch实现
    趣谈LINUX系统的进程间通信
    SAP 内码转外码
    Windows10下Git2.37.1安装及配置完整版
    (SVN+SSH)搭建SVN并使用SSH进行免密拉取推送代码
    springcloud3 指定nacos的服务名称和配置文件的group,名称空间
    测试工程师面试攻略:教你如何描述项目经验
  • 原文地址:https://blog.csdn.net/lbaihao/article/details/132872767