LWIP是TCP/IP协议栈的一种具体实现,本质就是对数据包的处理,在LWIP中使用一个被称为pbuf的结构管理数据包,
LWIP源码中的pbuf.c和pbuf.h这两个文件就是关于pbuf的,pbuf结构如下:

  1. struct pbuf
  2. {
  3. struct pbuf *next; //构成链表的时候指向下一个pbuf
  4. void *payload; //指向数据缓冲区
  5. u16_t tot_len; //pbuf链表中所有pbuf的数据长度
  6. u16_t len; //当前bpuf中的数据长度
  7. u8_t type; //pbuf类型
  8. u8_t flags; //状态
  9. u16_t ref; //用来记录当前pbuf被引用的次数
  10. };

数据类型

PBUF_RAM类型

  1. case PBUF_RAM:
  2. p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE\
  3. (SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
  4. if (p == NULL) {
  5. return NULL;
  6. }
  7. p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset));
  8. p->len = p->tot_len = length;
  9. p->next = NULL;
  10. p->type = type;
  11. break;

PBUF_RAM类型的pbuf空间是从LWIP的内存堆中申请得到的,协议栈和应用程序中的待发送数据就是采用的这种方法。
pbuf的申请是在pbuf_alloc()中进行的,

image.png

PBUF_POOL类型

  1. case PBUF_POOL:
  2. p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
  3. if (p == NULL)
  4. {
  5. PBUF_POOL_IS_EMPTY();
  6. return NULL;
  7. }
  8. p->type = type;
  9. p->next = NULL;
  10. p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset)));
  11. break;

PBUF_POOL类型的pbuf空间是从LWIP的内存池中申请得到的。
image.png

在LWIP初始化的时候就会自动的两类与pbuf相关的POOL:
MEMP_PBUF和MEMP_PBUF_POOL(在memp_std.h中)

  • MEMP_PBUF

    • 用于PBUF_REF和PBUF_ROM这两类的
  • MEMP_PBUF_POOL

    • 是用于PBUF_POOL类型的

PBUF_ROM和PBUF_REF类型

PBUF_ROM和PBUF_REF类型的pbuf空间也是从LWIP的内存池中申请得到的,分配方法都一样的,
他们使用内存池MEMP_PBUF,这两种类型申请的是指pbuf结构体的内存空间,并不包含数据空间,分配过程如下:

  1. case PBUF_ROM:
  2. case PBUF_REF:
  3. p = (struct pbuf *)memp_malloc(MEMP_PBUF);
  4. if (p == NULL)
  5. {
  6. return NULL;
  7. }
  8. p->payload = NULL;
  9. p->len = p->tot_len = length;
  10. p->next = NULL;
  11. p->type = type;
  12. break;

image.png

多种类型pbuf混合使用

image.png

数据包申请和释放

pbuf的申请和释放通过函数pbuf_alloc()和pbuf_free()来完成,
pbuf_alloc()函数和pbuf_free()函数原型如下:

  1. pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
  2. pbuf_free(struct pbuf *p)

pbuf_alloc()函数有两个重要的参数:

  • layer
    • layer决定是协议栈的哪一层申请的
    • layer决定了pbuf中的offset,也就是pbuf数据区中卫协议预留的首部空间
    • pbuf.h文件定义了一个枚举类型pbuf_layer来描述LWIP中的层,如下:
  • type,,
    • type决定申请的pbuf类型,
  1. typedef enum {
  2. PBUF_TRANSPORT,
  3. PBUF_IP,
  4. PBUF_LINK,
  5. PBUF_RAW
  6. } pbuf_layer;