Lwip中ref属性值设置及释放原理

Lwip中ref属性值设置及释放原理

1,背景:

在学习野火《LwIP 应用开发实战指南》中的pbuf时,对于ref这一属性值的设置以及如何根据ref删除同一数据包的pbuf的情况理解不是很清楚,在对比了网络上的不同文档后,对于一些细节上的描述予以补充。 注意:本文一些地方会直接使用野火文档的描述,感兴趣的读者请直接阅读野火文档。

2,pbuf结构体:

pbuf 就是一个描述协议栈中数据包的数据结构。

/** Main packet buffer struct */
struct pbuf
{
/** next pbuf in singly linked pbuf chain */
struct pbuf *next; 
/** pointer to the actual data in the buffer */
void *payload; 
u16_t tot_len; 
/** length of this buffer */
u16_t len; 
u8_t type_internal;
/** misc flags */
u8_t flags; 
LWIP_PBUF_REF_T ref; 
/** For incoming packets, this contains the input netif's index */
u8_t if_idx;
};

这里只讲解里面最重要的几个属性
(1) next :由于数据包可能会大于pbuf能够携带的最大数据量,所以需要多个pbuf来共同构成一个数据包,next指针可以指向下一个pbuf结构体。
(2) payload:指向pbuf携带的数据
(3) tot_len:包含当前payload指向的数据大小,加上后续所有pbuf中payload指向的数据大小。如果当前pbuf是列表中最后一个pbuf,由于没有后续的pbuf,所以tot_len的值等于当前payload指向的数据大小。
(4) len:当前payload指向的数据大小。

3,ref属性:记录被引用的次数。

把这个属性单独拿出来说,主要是因为很多文章里只讲到了ref在释放的时候的作用,而对于ref的值为什么这样设置说的比较模糊。其实,在查阅了Lwip源码后,会发现ref的值设置得十分巧妙。
首先这个记录被引用的次数,当pbuf被初始化时就会被设置为1,这是因为pbuf都会有个next执行指向它(第一个节点则是链表头指向它)。所以当这条链表只有一个数据包时(这个链表上的所有pbuf组合成一个数据包),每个pbuf的ref值都是1。
当这条链表有多个数据包时(其实就是Lwip调用pbuf_chain将两个链表合并成了一个),pbuf_chain()内会将第二条链表的第一个节点的ref值加一。即构成了ref的序列类似于1->1->2->1->1…
另外,当这个数据包被其他协议层使用到时也会进行类似操作。
在了解了上面的内容后,如何释放pbuf节点使得一个完整的数据包被释放就显得简单多了,只要每次把ref的值-1,检查是否为0,是就删除,然后访问下一个节点。由于第二个数据包的ref为2,减1后为1,所以第二个数据包不会比删除,且你会发现第二个数据包的ref序列也变成了类似于1->1->1…的格式。
下面是pbuf_chain()的源码

void
pbuf_chain(struct pbuf *h, struct pbuf *t)
{
  pbuf_cat(h, t);
  /* t is now referenced by h */
  pbuf_ref(t);
  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
}
void
pbuf_ref(struct pbuf *p)
{
  /* pbuf given? */
  if (p != NULL) {
    SYS_ARCH_SET(p->ref, (LWIP_PBUF_REF_T)(p->ref + 1));
    LWIP_ASSERT("pbuf ref overflow", p->ref > 0);
  }
}

4,举例验证

现在有ref序列号为以下的链表,对第一个数据包进行删除操作后的结果是?
3->3->3
答案是2->3->3,减一后不为0,pbuf不删除
1->1->2
答案是 …1,前两个pbuf 删除

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值