LWIP学习系列(三):lwip中pbuf结构体与内存管理

目录

一、pbuf结构体相关知识整理

(1)pbuf结构体与相关函数

(2)pbuf的类型

二、lwip中的内存管理(仅进行简单描述)

(1)内存管理相关宏定义

(2)内存堆mem

(3)内存池


一、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的类型

  1. PBUF_RAM 类型:
    PBUF_RAM 类型的pbuf的数据存放在RAM中(由内存堆分配而来),常用于发送数据的情况。
    在申请这种类型的pbuf时,协议栈会根据所需要的大小申请对应内存空间
    其中,申请的内存包含pbuf数据结构大小以及所需要的数据空间大小。
  2. PBUF_POOL 类型:
    PBUF_POOL类型的pbuf的数据结构大小以及所需要的数据空间大小也是连续的内存块中。
    但是这个连续的内存块是由内存池进行分配的。
  3. PBUF_ROMPBUF_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);

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃鱼的猫丿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值