LWIP_简记(5.数据包管理)

LWIP一句话记住就行:
一项工程,两份配置,三种内存分配,四套操作API,五步初始化,六个"数据流",七个数据结构
-------------------------------------------

先整链接:https://blog.csdn.net/XieWinter/article/details/99829412
这篇博文讲的特别清楚详细.

前言

再来自我总结:
lwip说到底也就是TCPIP协议,那本质就是数据的传递.
这里必须要强调一点儿:数据包和数据是两个完全不同的概念,前者包含后者.(虽然有点儿傻,但是真的要时刻谨记),理解pbuf和buffer.
因为用户只关系数据,但是在网络数据包中对于程序员更应该关心数据外的东东,比如包头(类型,大小,标记,检验和...)

PBUF

好了回到lwip上来,
在lwip中pbuf 就是一个描述协议栈中数据包的数据结构,LwIP 中在pbuf.c 和pubf.h 实现了协议栈数据包管理的所有函数与数据结构。
不失一般性我们进行提纲挈领的总结:
1.PBUF结构:

185 /** Main packet buffer struct */
186 struct pbuf {
187   /** next pbuf in singly linked pbuf chain */
188   struct pbuf *next;
189  //由此可以看出是个单向链表
190   /** pointer to the actual data in the buffer */
191   void *payload;
192  //指向真实数据(buffer惯用来表示数据)的首地址
193   /**
194    * total length of this buffer and all next buffers in chain
195    * belonging to the same packet.
196    *
197    * For non-queue packet chains this is the invariant:
198    * p->tot_len == p->len + (p->next? p->next->tot_len: 0)
199    */
200   u16_t tot_len;
201  //等于当前len+下一个tot_len
202   /** length of this buffer */
203   u16_t len;
204  
205   /** a bit field indicating pbuf type and allocation sources
206       (see PBUF_TYPE_FLAG_*, PBUF_ALLOC_FLAG_* and PBUF_TYPE_ALLOC_SRC_MASK)
207     */
208   u8_t type_internal;
209  
210   /** misc flags */
211   u8_t flags;
212  
213   /**
214    * the reference count always equals the number of pointers
215    * that refer to this pbuf. This can be pointers from an application,
216    * the stack itself, or pbuf->next pointers from a chain.
217    */
218   LWIP_PBUF_REF_T ref;
219   //被引用次数                                                                                                                                                                 
220   /** For incoming packets, this contains the input netif's index */
221   u8_t if_idx;
222  //用于记录传入的数据包中输入netif 的索引,也就是netif 中num 字段
223 };

看代码可能没有上图来的刺激:具体字段的解释上面注释已经说的很清楚了.
在这里插入图片描述
2.PBUF tot_len字段
一定要注意计算方式:
tot_len = len + Next_tot_len.
由此可以看出只有第一个pbuf结构的tot_len表示了整个数据包的大小.

3.PBUF类型


/**
 * @ingroup pbuf
 * Enumeration of pbuf types
 */
typedef enum {
  /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload
      are allocated in one piece of contiguous memory (so the first payload byte
      can be calculated from struct pbuf).
      pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might
      change in future versions).
      This should be used for all OUTGOING packets (TX).*/
  PBUF_RAM = (PBUF_ALLOC_FLAG_DATA_CONTIGUOUS | PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS | PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP),
  /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in
      totally different memory areas. Since it points to ROM, payload does not
      have to be copied when queued for transmission. */
  PBUF_ROM = PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF,
  /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change
      so it has to be duplicated when queued before transmitting, depending on
      who has a 'ref' to it. */
  PBUF_REF = (PBUF_TYPE_FLAG_DATA_VOLATILE | PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF),
  /** pbuf payload refers to RAM. This one comes from a pool and should be used
      for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct
      pbuf and its payload are allocated in one piece of contiguous memory (so
      the first payload byte can be calculated from struct pbuf).
      Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing,
      you are unable to receive TCP acks! */
  PBUF_POOL = (PBUF_ALLOC_FLAG_RX | PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS | PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL)
} pbuf_type;

具体类型之间的差异就不多说了,前面给的链接讲的很清楚了.

4.PBUF操作


struct pbuf *
pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
//留意三个参数:数据包在那一层被申请,长度,类型

理解一下第一个参数:
因为pbuf结构贯穿整个tcpip协议层,我们知道每一层的数据包头部是不一样的.所以需要预留协议首部空间.

pbuf_free()

这里需要提出来的就是ref字段了.

1.申请pbuf时ref字段初始化为1.
2.释放时先将ref减1,只有ref减到为0,才能被释放.
3.只有pbuf首节点才能被释放.

关于pbuf的具体使用,比如数据*payload是怎样给到buffer的,我们后面遇到了再细看.
-------------------------------------------
这期就到这里了,LWIP想怎么玩就怎么玩,我们下期再见.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章