关闭

lwip包缓冲区pbufs

标签: lwippbuf数据缓冲区pbuf类型
1004人阅读 评论(0) 收藏 举报
分类:
lwip信息包是存储在pbufs中,pbufs作为lwip的数据缓冲区,是由pbuf结构组成的链表。数据存在pbufs链中各个pbuf节点所指向存储块中。

pbuf结构体的定义如下:
struct pbuf {
  struct pbuf *next;   //pbuf链中下一个pbuf的地址

  void *payload; //指向该pbuf的数据存储区的首地址

  u16_t tot_len;//   当前 pbuf 和其后所有 pbuf的有效数据的长度

  u16_t len; // 当前pbuf中的有效数据长度

  u8_t /*pbuf_type*/ type;  pbuf的类型

  u8_t flags; //  标志位

  u16_t ref;// ref 字段表示该 pbuf 被引用的次数。该结构体每被引用一次,ref的值加1,当解除引用是,ref减1。只有当ref的值为0的时候,该结构体才能被删除成功,否则删除失败。
};

pbuf中的type成员表示pbuf的类型
pbuf一共有四种类型
在pbuf.h中的类型包含在pbuf_type枚举中。如下
typedef enum {
  PBUF_RAM, /* pbuf data is stored in RAM */
  PBUF_ROM, /* pbuf data is stored in ROM */
  PBUF_REF, /* pbuf comes from the pbuf pool */
  PBUF_POOL /* pbuf payload refers to RAM */
} pbuf_type;

1:PBUF_RAM类型的pbuf是通过内存堆分配得到的。在申请PBUF_RAM类型时,内存堆中分配相应的大小地址连续的内存块,其容量能够存储pbuf结构体+数据缓冲区。数据缓冲区可能包括数据包头+数据也可以没有数据包头,具体看申请的方式。如图所示:

2: PBUF_POOL 类型的它由分配自固定大小的 pbufs 池里的固定大小的 pbufs 组成。其他的跟PBUF_RAM很相似,其结构体+数据缓冲区也是存在于连续的内存块中。如图:一个来自于 pbuf 池中的被链接的 PBUF_POOL pbuf,这些节点的大小都是大小都是一样大的:


3:PBUF_ROM类型的pbuf是从内存堆中分配申请一个相应的结构头,并不会申请数据区的空间。其数据空间不跟结构头在一块连续的空间上,数据空间有在ROM上,有结构头中的payload指针成员指向该空间。包含有数据 包头的数据不能存储在该类型的pbuf上。

4:PBUF_REF和PBUF_ROM 类型的 pbuf 基本相同,但是数据空间在RAM上。

PBUF_REF和PBUF_ROM的结构如图所示

数据包pbufs链表可以由以上四种pbuf结构中的任意类型混合组成。

pbuf的申请
pbuf的申请函数struct pbuf *  pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
其中layer跟报文的所在协议的层有关系,不同的协议层的数据包头不一样,链表第一个节点的在数据缓冲区的包头大小也不一样。
与pbuf相关的layer有四种,PBUF_TRANSPORT(传输层), PBUF_IP(ip层),PBUF_LINK(链路层),PBUF_RAW(RAW类型)
例如,若是传输层pbuf,其报文包头占的大小为链路层报文的头部+ip头部+传输层的头部。
case PBUF_TRANSPORT:
 offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
 break;
若是ip层pbuf,offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;

当申请的pbuf类型为PBUF_POOL时,先想pbuf内存池申请一块内存。
p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
第一块的内存块的数据存储区的首地址需要跳过数据包头的长度,即offset
p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset)))
若是一块的容量不够,则继续申请第二块,还不够继续申请。这些从内存申请到的内存块,组成链表。并且返回首块的地址。

当申请的pbuf类型为PBUF_RAM时,调用mem_malloc,直接向堆栈的申请。
p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
当为PBUF_ROM和PBUF_REF,调用mem_malloc,直接向堆栈的申请不含数据区pbuf结构大小的内存块。

pbuf的释放
pbuf的释放由函数void  pbuf_realloc(struct pbuf *p, u16_t new_len)实现
在释放pbuf的时候,若成员pbuf结构体成员ref为0 的时候(被引用数),才能进行释放。
若第一个节点不能被释放,那么链表后面的节点的ref也至少为1。不可能被释放。只有第一个节点被释放后,后面的节点才有可能被依此释放。
























0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:48052次
    • 积分:918
    • 等级:
    • 排名:千里之外
    • 原创:44篇
    • 转载:4篇
    • 译文:0篇
    • 评论:1条
    文章分类