lwip的数据包结构Pbuf
TCP/IP是一种数据通信机制,因此,协议栈的实现本质上就是对数据包进行处理。数据包管理应该能提供一种高效的机制,使协议栈各层能对数据包进行灵活的处理,同时减少数据在各层间传递时的时间与空间开销,这是提高协议栈工作效率的关键点。在BSD的实现中,有个描述和管理数据包的结构叫做mbuf,而在LwIP中,也有个类似的结构,称之为pbuf。在本文中,将讨论LwIP的数据包管理是怎样合理利用动态内存池策略和动态内存堆分配策略。
- LwIP的层间结构与编程模型
- 数据包管理结构pbuf
- 数据包管理相关操作函数
一、LwIP的层间结构与编程模型
1. LwIp的分层特点
在标准TCP/IP协议结构中,各个层都被描述为一个独立的模块形式,每一层负责完成一个独立的通信问题。如果单片机按照这种严格的分层模式来实现TCP/IP协议,会使数据包在各层间的递交变得非常慢,因为它涉及一系列的内存拷贝问题,因此,系统总体系能也会受到影响。为避免此,LwIP内部并没有采用完整的分层结构,它会假设各层间的部分数据结构和实现原理在其他层是可见的。这样,在数据包递交过程中,各层协议可以直接对数据包中属于其他层间协议的字段进行操作,这将使整个协议栈对数据包的操作更加灵活。
LwIP实现时,参考了TCP/IP协议的分层思想,即每层都在一个单独的模块中实现,并为其他层次模块提供一些输入/输出函数。但即使这样,严格上说,LwIP并没有遵循严格的分层机制,正如前面讨论的那样,为了节省时间和空间上的开销,各个层间之间可能存在交叉存取的现象。
另一方面,在许多其他TCP/IP协议的实现中,即使内核各层存在着一定的交错现象,但在用户应用程序和协议栈内核之间也会保持着很明显的分层建构。但在小型嵌入式设备使用得操作系统中,操作系统代码和用户程序代码之间通常都没有出现明显分层的现象,这种方式允许用户程序和操作系统内核之间使用更多宽松的方式进行通信。如共享内存等。这可以避免数据在用户程序和LwIP协议栈之间拷贝时的时间和内存开销。
2. 协议进程模型
LwIP协议栈内核与操作系统内核互相隔离,而同时整个协议栈作为操作系统中的一个单独进程而存在。用户应用程序可以驻留在协议栈内核的进程中(raw/callback API),也可以实现为一个单独的进程(sequential API和socket API)。
二、数据包管理
1. 数据包结构pbuf
包缓冲区 pbufs
pbuf 是 LwIP 信息包的内部表示,为最小限度协议栈的特殊需求而设计。pbufs 与 BSD
实现中使用的 mbufs 相似。pbuf 结构即支持动态内存分配保存信息包内容,也支持让信息
包数据驻留在静态存储区。pbufs 可以在一个链表中链接在一起,被称作一个 pbuf链,这样
一个信息包可以穿越几个 pbufs。
pbufs有三种类型:PBUF RAM、PBUF ROM、PBUF POOL。图 1 所示的pbuf为
PBUF RAM 类型,包数据存储在由 pbuf 子系统管理的存储区中
在Pbuf.h里面
struct pbuf {
struct pbuf *next;//构成pbuf链表时指向一下一个pbuf结构
void *payload;//数据指针,指向该pbuf所记录的数据区域
/**
* total length of this buffer and all next buffers in chain
* belonging to the same packet.
*
* For non-queue packet chains this is the invariant:
* p->tot_len == p->len + (p->next? p->next->tot_len: 0)
*/
u16_t tot_len;//当前pbuf及其后续所有pbuf中包含的数据总长度
/** length of this buffer */
u16_t len;//当前pbuf的数据的长度
/** pbuf_type as u8_t instead of enum to save space */
u8_t /*pbuf_type*/ type;//当前pbuf的类型
/** misc flags */
u8_t flags;//状态位,未使用到
/**
* the reference count always equals the number of pointers
* that refer to this pbuf. This can be pointers from an application,
* the stack itself, or pbuf->next pointers from a chain.
*/
u16_t ref;//指向该pbuf的指针数,即该pbuf被引用的次数,初始时为1
};
2. pbuf类型