目录
一、pbuf结构体相关知识整理
由上一篇:LWIP学习系列(二):STM32中ETH外设的配置与LWIP的结合使用 中,底层数据的传输都是经过lwip封装成pbuf的格式,然后在对pbuf进行协议层之间的传输。
这一篇,就整理一下有关pbuf的相关内容与知识
(1)pbuf结构体与相关函数
- pbuf结构体
/** lwip中主要的数据包缓存结构体 */
struct pbuf {
/** 下一个pbuf数据包 */
struct pbuf *next;
/** 指向实际数据地址的指针 */
void *payload;
/**
* 数据包的总长度。
* 一个数据包可能由很多个pbuf组成, tot_len表示当前的pbuf长度加上这个数据包余下pbuf的长度
* 如:最后一个pbuf的 tot_len == len
*/
u16_t tot_len;
/** 该pbuf的长度 */
u16_t len;
/** 该pbuf的类型 (共有4种pbuf类型,不同中类型表示pbuf的数据存储在不同的区域) */
u8_t type;
/** 混合标志位 */
u8_t flags;
/** pbuf被引用的次数 */
u16_t ref;
};
-
pbuf相关函数原型
/**
* pbuf 的申请函数
* layer 表示在协议层中的那一层,协议栈会根据对应层申请头部信息所需要的空间
* length 表示申请所需要的空间
* type 表示申请什么类型的pbuf
*/
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type);
/** pbuf 的释放函数 */
u8_t pbuf_free(struct pbuf *p);
(2)pbuf的类型
- PBUF_RAM 类型:
PBUF_RAM 类型的pbuf的数据存放在RAM中(由内存堆分配而来),常用于发送数据的情况。
在申请这种类型的pbuf时,协议栈会根据所需要的大小申请对应内存空间。
其中,申请的内存包含pbuf数据结构大小以及所需要的数据空间大小。 - PBUF_POOL 类型:
PBUF_POOL类型的pbuf的数据结构大小以及所需要的数据空间大小也是连续的内存块中。
但是这个连续的内存块是由内存池进行分配的。 - PBUF_ROM 与 PBUF_PEF 类型
PBUF_ROM 与 PBUF_PEF ,在内存池申请的pbuf只包含pbuf的数据结构大小。
PBUF_ROM 存放的数据区域在ROM中。
PBUF_PEF 存放的数据区域在RAM中。(与PBUF_RAM 相比,就是pbuf数据结构内存与所存放数据区域的内存是不连续的)
二、lwip中的内存管理(仅进行简单描述)
(1)内存管理相关宏定义
- MEMP_MEM_MALLOC :修改为 1 时,使用LwIP的动态内存分配(使用mem_alloc 与 mem_free来分配空间,而不是通过LwIP的内存池分配)
- MEM_LIBC_MALLOC :修改为 1 时,使用标准C库自带的内存分配(malloc 与 free)
- MEM_USE_POOLS :修改为 1 时,使用内存池来替代其他分配策略。当使用动态内存池分配时,则不能使用标准C库的内存分配
(2)内存堆mem
1.内存堆mem 的结构体
struct mem {
/** 下一块内存块的地址偏移量 */
mem_size_t next;
/** 上一块内存块的地址偏移量 */
mem_size_t prev;
/** 判断当前内存块是否有被使用 */
u8_t used;
};
2.内存堆mem 中的一些全局变量
/** 内存堆 ram_heap, 由LWIP_DECLARE_MEMORY_ALIGNED定义一个 ram_heap
* 如果需要将内存堆指向外部存储器,则将LWIP_RAM_HEAP_POINTER 指向外部存储器的一个void 型地址
*/
#ifndef LWIP_RAM_HEAP_POINTER
LWIP_DECLARE_MEMORY_ALIGNED(ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM));
#define LWIP_RAM_HEAP_POINTER ram_heap
#endif
/** ram是一个全局指针变量,指向 内存堆对齐后 的起始地址 */
static u8_t *ram;
/** ram_end是一个mem指针变量,指向 内存堆 的末尾地址, 总是不被使用! */
static struct mem *ram_end;
/** lfree是一个mem指针变量,指向 低地址的空闲内存块*/
static struct mem *lfree;
3.内存堆mem 的申请与释放
/** 根据size 从ram_heap处分配对应大小的空间(通过遍历的形式查找),并且返回对应地址 */
void *mem_malloc(mem_size_t size)
void *mem_calloc(mem_size_t count, mem_size_t size)
/** 直接将对应内存空间的 mem->used = 0, 就相当于将该内存块给释放了 */
void mem_free(void *rmem)
(3)内存池
1、动态内存堆使用内存池进行管理
当动态内存 使用内存池管理机制的时候,还需要再定义一个lwippools.h,并且添加如图上的宏定义。以上宏定义的意义是分配20个256字节长度的内存块、10个512字节的内存块、5个1512字节的内存块。
2、内存池的全局变量与相关枚举
- 通过 LWIP_MEMPOOL(name,num,size,desc) 来定义相关类型的内存池
- 可以通过 下面代码得知,LWIP_MEMPOOL(name,num,size,desc) 定义了
u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)] (内存池实际存放空间)
static struct memp *memp_tab_ ## name (内存池的索引或标签:指向内存池的首地址)
const struct memp_desc memp_ ## name (内存池的描述结构体)
/* LWIP_MEMPOOL 宏定义*/
#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
#include "lwip/priv/memp_std.h"
/* LWIP_MEMPOOL_DECLARE 宏定义作用:声明内存池宏定义、大小、数量等 */
#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \
\
LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \
\
static struct memp *memp_tab_ ## name; \
\
const struct memp_desc memp_ ## name = { \
DECLARE_LWIP_MEMPOOL_DESC(desc) \
LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \
LWIP_MEM_ALIGN_SIZE(size), \
(num), \
memp_memory_ ## name ## _base, \
&memp_tab_ ## name \
};
/** LWIP_DECLARE_MEMORY_ALIGNED 宏定义作用:内存池实际存放空间 **/
#ifndef LWIP_DECLARE_MEMORY_ALIGNED
#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)]
#endif
/** LWIP_MEMPOOL_DECLARE_STATS_INSTANCE宏定义作用:声明memp_stats_ ## name 的宏定义 **/
LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name)
#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name)
可以由下图得知 memp_tab 与 memp_memory 之间的关系:
/* 内存池 */
const struct memp_desc *const memp_pools[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
#include "lwip/priv/memp_std.h"
};
/* 内存池枚举 */
/** Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */
typedef enum {
#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,
#include "lwip/priv/memp_std.h"
MEMP_MAX
} memp_t;
3、内存池的申请与释放
/* 内存池的初始化 */
void memp_init(void);
/* 内存的申请 */
memp_malloc(memp_t type);
static void *do_memp_malloc_pool(const struct memp_desc *desc);
/* 内存的释放 */
memp_free(memp_t type, void *mem);
static void do_memp_free_pool(const struct memp_desc *desc, void *mem);