欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

LwIP之动态内存池

发布时间:2025/3/15 编程问答 39 豆豆
生活随笔 收集整理的这篇文章主要介绍了 LwIP之动态内存池 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

先看memp_t,这是一个枚举体,定义了所有内存池的类型。

typedef enum { #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, #include "lwip/memp_std.h"MEMP_MAX } memp_t;

枚举体包含了一个头文件,对头文件进行展开

typedef enum { #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,......#if LWIP_RAW LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") #endif#if LWIP_UDP LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") #endif#if LWIP_TCP LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") #endif......#undef LWIP_MEMPOOL......MEMP_MAX } memp_t;

进一步,对宏LWIP_MEMPOOL进行展开,最终得到memp_t类型如下

typedef enum {MEMP_RAW_PCB,MEMP_UDP_PCB,MEMP_TCP_PCB,MEMP_TCP_PCB_LISTEN,MEMP_TCP_SEG,......MEMP_MAX } memp_t;

按照上面的原理,编译的时候,会建立起来几个全局变量

/* 各个内存池单元大小 */ const u16_t memp_sizes[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), #include "lwip/memp_std.h" }; 展开后 const u16_t memp_sizes[MEMP_MAX] = {LWIP_MEM_ALIGN_SIZE(sizeof(struct raw_pcb)),LWIP_MEM_ALIGN_SIZE(sizeof(struct udp_pcb)),LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_pcb)),LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_pcb_listen)),LWIP_MEM_ALIGN_SIZE(sizeof(struct tcp_seg)),... }; /* 各个内存池单元个数数组 */ static const u16_t memp_num[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) (num), #include "lwip/memp_std.h" }; 展开后 static const u16_t memp_num[MEMP_MAX] = {MEMP_NUM_RAW_PCB,MEMP_NUM_UDP_PCB,MEMP_NUM_TCP_PCB,MEMP_NUM_TCP_PCB_LISTEN,MEMP_NUM_TCP_SEG,... }; /* 所有内存池空间 */ static u8_t memp_memory[MEM_ALIGNMENT - 1 #define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) #include "lwip/memp_std.h" ]; 展开后 static u8_t memp_memory[MEM_ALIGNMENT - 1 + (MEMP_NUM_RAW_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct raw_pcb)))+ (MEMP_NUM_UDP_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct udp_pcb)))+ (MEMP_NUM_TCP_PCB) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_pcb)))+ (MEMP_NUM_TCP_PCB_LISTEN) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_pcb_listen)))+ (MEMP_NUM_TCP_SEG) * (MEMP_SIZE + MEMP_ALIGN_SIZE(sizeof(struct tcp_seg))) ];

接下来再看一个结构体,这个结构体用于将内存池单元连接成链表

/* 内存池单元结构体 */ struct memp {struct memp *next; };

而下面这个数组用于指向各个内存池链表中的第一个空闲单元

static struct memp *memp_tab[MEMP_MAX];

 

接下来看一下内存池相关的API

/* 初始化内存池 */ void memp_init(void) {struct memp *memp;u16_t i, j;/* 内存池所在内存地址 */memp = LWIP_MEM_ALIGN(memp_memory);/* 将内存分割成各个内存池 */for (i = 0; i < MEMP_MAX; ++i) {/* 将各个内存池单元连接成链表 */memp_tab[i] = NULL;for (j = 0; j < memp_num[i]; ++j) {memp->next = memp_tab[i];memp_tab[i] = memp;memp = (struct memp *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]);}} }

初始化完成之后,内存池空间被组织成如下结构 

                                          

/* 申请一个内存池单元 */ void *memp_malloc(memp_t type) {struct memp *memp;/* 内存池空闲单元指针 */memp = memp_tab[type];/* 链表头部取出一个单元 */if (memp != NULL) {memp_tab[type] = memp->next;memp = (struct memp *)((u8_t *)memp + MEMP_SIZE);}/* 返回内存地址 */return memp; } /* 释放一个内存池单元 */ void memp_free(memp_t type, void *mem) {struct memp *memp;if (mem == NULL) {return;}/* 将内存地址转换为内存池单元指针 */memp = (struct memp *)((u8_t*)mem - MEMP_SIZE);/* 将内存池单元插入相应链表头部 */memp->next = memp_tab[type]; memp_tab[type] = memp; }

 

总结

以上是生活随笔为你收集整理的LwIP之动态内存池的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。