LWIP是TCP/IP协议栈的一种具体实现,本质就是对数据包的处理,在LWIP中使用一个被称为pbuf的结构管理数据包,
LWIP源码中的pbuf.c和pbuf.h这两个文件就是关于pbuf的,pbuf结构如下:
struct pbuf{struct pbuf *next; //构成链表的时候指向下一个pbufvoid *payload; //指向数据缓冲区u16_t tot_len; //pbuf链表中所有pbuf的数据长度u16_t len; //当前bpuf中的数据长度u8_t type; //pbuf类型u8_t flags; //状态u16_t ref; //用来记录当前pbuf被引用的次数};
数据类型
PBUF_RAM类型
case PBUF_RAM:p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE\(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));if (p == NULL) {return NULL;}p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset));p->len = p->tot_len = length;p->next = NULL;p->type = type;break;
PBUF_RAM类型的pbuf空间是从LWIP的内存堆中申请得到的,协议栈和应用程序中的待发送数据就是采用的这种方法。
pbuf的申请是在pbuf_alloc()中进行的,
PBUF_POOL类型
case PBUF_POOL:p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);if (p == NULL){PBUF_POOL_IS_EMPTY();return NULL;}p->type = type;p->next = NULL;p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset)));break;
PBUF_POOL类型的pbuf空间是从LWIP的内存池中申请得到的。
在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结构体的内存空间,并不包含数据空间,分配过程如下:
case PBUF_ROM:case PBUF_REF:p = (struct pbuf *)memp_malloc(MEMP_PBUF);if (p == NULL){return NULL;}p->payload = NULL;p->len = p->tot_len = length;p->next = NULL;p->type = type;break;

多种类型pbuf混合使用

数据包申请和释放
pbuf的申请和释放通过函数pbuf_alloc()和pbuf_free()来完成,
pbuf_alloc()函数和pbuf_free()函数原型如下:
pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)pbuf_free(struct pbuf *p)
pbuf_alloc()函数有两个重要的参数:
- layer
- layer决定是协议栈的哪一层申请的
- layer决定了pbuf中的offset,也就是pbuf数据区中卫协议预留的首部空间
- pbuf.h文件定义了一个枚举类型pbuf_layer来描述LWIP中的层,如下:
- type,,
- type决定申请的pbuf类型,
typedef enum {PBUF_TRANSPORT,PBUF_IP,PBUF_LINK,PBUF_RAW} pbuf_layer;
