一篇带给你Lwip数据包管理

开发 前端
LWIP是TCP/IP协议栈的一种具体实现,本质就是对数据包的处理,在LWIP中使用一个被称为pbuf的结构管理数据包,LWIP源码中的pbuf.c和pbuf.h这两个文件就是关于pbuf的,本篇就带你一起学习Lwip数据包管理。

[[392397]]

1.1、pbuf结构

LWIP是TCP/IP协议栈的一种具体实现,本质就是对数据包的处理,在LWIP中使用一个被称为pbuf的结构管理数据包,LWIP源码中的pbuf.c和pbuf.h这两个文件就是关于pbuf的,pbuf结构如下:

在pbuf.h文件中


下面是翻译版

  1. struct pbuf 
  2.      struct pbuf      *next;  //构成链表的时候指向下一个pbuf 
  3.      void              *payload; //指向数据缓冲区 
  4.      u16_t   tot_len; //pbuf链表中所有pbuf的数据长度 
  5.      u16_t   len;  //当前bpuf中的数据长度 
  6.      u8_t     type;  //pbuf类型 
  7.      u8_t   flags;  //状态 
  8.      u16_t   ref;  //用来记录当前pbuf被引用的次数 
  9. }; 

1.2、tot_len

说一下tot_len的讲解

大家最好理解一下英文的意思,我说完中文,再回头看一下英文。

1.3、type

下面我们看一下type

从这里可是使用编译器跳过去

也就是pbuf_type的类型有

 

  1. typedef enum 
  2.     PBUF_RAM,  //pbuf数据紧跟着pbuf的结构存储,数据存储在ram中 
  3.     PBUF_ROM,    //pbuf数据存储在rom中 
  4.     PBUF_REF,  //pbuf数据存储在ram中,但是与pbuf结构的位置无关 
  5.     PBUF_POOL   //pbuf结构和其数据存储在同一个内存池中 
  6. } pbuf_type; 

分别讲一下这四种类型

1.3.1、PBUF_RAM

PBUF_RAM类型的pbuf空间是从LWIP的内存堆中申请得到的,协议栈和应用程序中的待发送数据就是采用的这种方法,pbuf的申请是在pbuf_alloc()中进行的,PBUF_RAM类型的申请代码如下:

在pbuf.c文件中pbuf_alloc函数

看到mem_malloc()函数,知道是从内存堆里申请的内存

申请的大小是:pbuf的大小+ 实际申请的大小

offset是一个偏移,这个offset里面用来存储一些首部字段,如TCP报文首部,IP首部等等。

最终申请出来的PBUF_RAM类型的pbuf结构是

下图1部分的就是pbuf结构部分

2部分是offset部分

1.3.2、PBUF_POOL

PBUF_POOL类型的pbuf空间是从LWIP的内存池中申请得到的,因为是从内存池中申请的,所以这种类型的pbuf分配时间极短,在网卡接收数据包时,我们使用这种方式:

在pbuf.c文件中pbuf_alloc函数

既然PBUF_POOL类型是在内存池中申请的,那么就必须得有对应的POOL类型,在LWIP初始化的时候就会自动的两类与pbuf相关的POOL:MEMP_PBUF和MEMP_PBUF_POOL(在memp_std.h中),其中MEMP_PBUF是用于PBUF_REF和PBUF_ROM这两类的,MEMP_PBUF_POOL是用于PBUF_POOL类型的。

事实上应用程序发送和接收的数据量可能很大,但是内存池类型的内存分配每次分配到的大小是固定的,因此可能会需要进行多次分配,最终的分配成功的PBUF_POOL类型的pbuf如下图:

注意看,上图中只有第一个pbuf有offset,这是因为这都是一个数据包的,因此只需要一个offset来存储有关数据包的信息,其他的pbuf就不需要了!这部分也是在代码中体现过的

第一个pbuf的payload

后续的pbuf的payload


 

1.3.3、PBUF_ROM和PBUF_REF

PBUF_ROM和PBUF_REF类型的pbuf空间也是从LWIP的内存池中申请得到的,分配方法都一样的,他们使用内存池MEMP_PBUF,这两种类型申请的是指pbuf结构体的内存空间,并不包含数据空间,分配过程如下:

PBUF_ROM和PBUF_REF并没有给数据空间申请内存,那么他们的数据空间在哪里呢?这两个的数据空间可以应用其他地方的内存,不同之处在于PBUF_ROM的数据空间在ROM中,PBUF_REF的数据空间在RAM中。这两种类型的pbuf最终如下:

1.3.4、多种类型pbuf混合使用

实际的数据包可能会同时使用多种类型的pbuf,如下图:

02数据包申请和释放

pbuf的申请和释放通过函数pbuf_alloc()和pbuf_free()来完成,pbuf_alloc()函数和pbuf_free()函数原型如下:

  1. pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) 
  2. pbuf_free(struct pbuf *p) 

pbuf_alloc()函数有两个重要的参数:layer和type,layer决定是协议栈的哪一层申请的,type决定申请的pbuf类型,layer决定了pbuf中的offset,也就是pbuf数据区中卫协议预留的首部空间,pbuf.h文件定义了一个枚举类型pbuf_layer来描述LWIP中的层,如下:

  1. typedef enum {    
  2.   PBUF_TRANSPORT,    
  3.   PBUF_IP,   
  4.   PBUF_LINK,    
  5.   PBUF_RAW  
  6. } pbuf_layer; 

 

责任编辑:姜华 来源: 知晓编程
相关推荐

2021-04-23 08:31:50

Lwipnetif网络开发

2021-07-12 06:11:14

SkyWalking 仪表板UI篇

2022-04-29 14:38:49

class文件结构分析

2023-03-29 07:45:58

VS编辑区编程工具

2021-03-12 09:21:31

MySQL数据库逻辑架构

2021-01-28 08:55:48

Elasticsear数据库数据存储

2021-04-01 10:51:55

MySQL锁机制数据库

2024-06-13 08:34:48

2022-02-17 08:53:38

ElasticSea集群部署

2021-04-08 11:00:56

CountDownLaJava进阶开发

2021-06-21 14:36:46

Vite 前端工程化工具

2022-03-22 09:09:17

HookReact前端

2021-07-21 09:48:20

etcd-wal模块解析数据库

2021-04-14 14:16:58

HttpHttp协议网络协议

2022-02-25 15:50:05

OpenHarmonToggle组件鸿蒙

2023-03-13 09:31:04

2021-04-23 08:59:35

ClickHouse集群搭建数据库

2021-10-28 08:51:53

GPIO软件框架 Linux

2021-07-08 07:30:13

Webpack 前端Tree shakin

2021-04-14 07:55:45

Swift 协议Protocol
点赞
收藏

51CTO技术栈公众号