Memory Manager

概述

1
2
3
#内存管理机制
1. 动态内存池管理
2. 动态内存堆管理

前提

动态内存管理,肯定会出现堆区 已用 未用 交替的情况

内存分配的重要性

内存管理策略与内存分配效率是衡量系统性能的重要因素

内存分配策略

动态内存池

原理

  • 系统启动前,预先分配一块区域
  • 将内存分为 固定大小 [ 4B 8B 16B] 的区域
  • 用链表链接起来

特点

  • 效率高: 内存释放与分配只是链表的增 删操作
  • 内存浪费: 大小固定,预先分配
  • 适合固定的数据结构进行空间的分配 [TCP首部 IP首部]

动态内存堆

原理

  • 仅存在一个空闲内存块,长度m 大于用户的请求n

    ​ m中前n个字节返回给用户,剩余的 m-n 个字节,重新组织一个空闲块

  • 多个空闲块,长度大于n

    1. 首次拟合

      申请: 从空闲链表头查找,找到第一个

      释放: 插入链表头

    2. 最佳拟合

      申请: 空闲链表中找到长度和n最接近的空闲块 [空闲链表一般按照大小排序]

      释放: 遍历链表插入到合适的位置[大小顺序]

    3. 最差拟合

      申请: 空闲链表按照大小排序,每次都将链表头的内存分配给用户[最大的区域]

      释放: 遍历链表插入到合适的位置[大小顺序]

特点

  • 最佳拟合
    1. 内存请求大小范围较广 [每次分配都是找最接近的,大的空闲块会被保护不被使用]
    2. 缺点: 产生很小甚至无法被使用的内存块
  • 最差拟合
    1. 内存请求大小范围较窄 [每次选择最大的,使得各个块大小趋于均匀]
  • 首次拟合
    1. 不知道内存请求范围 [ 分配是随机的]

动态内存池

1
2
只能分配固定大小的内存空间,用户必须知道各个类型的POOL,以及这个类型POOL的个数
如果用户对内核结构足够了解,就能灵活配置各个POOL的数量,从而优化系统性能

源码文件

memp.c memp.h

结构体

1
2
3
4
5
6
7
1. memp_t	    :  每个类型	宏定义,枚举
2. memp_sizes : 每个类型 数据结构占用内存的大小
3. memp_num : 每个类型 数据结构个数
4. memp_desc : 每个类型 对应的字符描述
5. memp_memory : 每个类型 需要的内存 [一维数组,目的是预先分配内存]
6. memp_table : 每个类型 缓冲池的第一个空闲POOL
7. memp : 每个类型 缓冲池被连接成一个链表

函数

1
2
3
void  memp_init(void);
void *memp_malloc(memp_t type);
void memp_free(memp_t type, void *mem);

memp_init

  1. memp_memory : 各个类型缓冲池每项 链接成链表
  2. memp_tab : 各个类型缓冲池 链表头部

memp_alloc

​ 从对应的链表中取出内存,并返回

memp_free

动态内存堆

本质: 对一个事先定义好的内存块进行合理有效的组织和管理

数据结构

1
2
3
4
1. 内存块大小具有最小限制,MIN_SIZE = 12
2. 如果MIN_SIZE 太小,导致大的内存块 被不断细分为小的内存块
如果MIN_SIZE 太大,导致内存浪费
3. 内存回收函数查看附近是否空闲,合并成一个大的内存块

C语言技巧

枚举定义

1
2
3
4
5
typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/memp_std.h"
MEMP_MAX
} memp_t;
1
2
3
4
5
6
7
8
#if LWIP_RAW
LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB")
#endif /* LWIP_RAW */

#if LWIP_UDP
LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB")
#endif /* LWIP_UDP */
。。。。。
1
2
3
4
5
6
typedef enum {
MEMP_RAW_PCB,
MEMP_UDP_PCB,
。。。。
MEMP_MAX
} memp_t;
undefined