SylixOS中netdev_pbuf_alloc函数分析

1.netdev_pbuf_alloc函数简介

netdev_pbuf_alloc是网卡驱动中的内存申请函数,申请一块缓冲区用于存放网络报文数据。

成都创新互联专注于企业全网整合营销推广、网站重做改版、云龙网站定制设计、自适应品牌网站建设、H5页面制作成都商城网站开发、集团公司官网建设、外贸营销网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为云龙等各大城市提供网站开发制作服务。

2.pbuf结构分析

netdev_pbuf_alloc函数以pbuf结构申请内存空间,如程序清单 2.1所示。

程序清单 2.1  pbuf结构

struct pbuf {
    struct pbuf      *next;                                                                  
    void             *payload;
    u16_t            tot_len;
    u16_t            len;
    u8_t             type;
    u8_t             flags;
    u16_t            ref;
};

3.pbuf_alloc函数封装

netdev_pbuf_alloc函数是pbuf_alloc函数的函数封装,对外提供的函数接口只带有一个参数用于指定申请的缓冲区大小。而pbuf_alloc函数有三个参数,分别是申请的pbuf数据缓冲区是否带有偏移,数据缓冲区大小及缓冲区类型。在netdev_pbuf_alloc函数中,申请的pbuf结构缓冲区数据偏移固定为0,缓冲区类型为PBUF_POOL。netdev_pbuf_alloc函数传入的第二个参数缓冲区大小在调用pbuf_alloc函数申请pbuf结构时会被增加一个reserve长度,用于协议栈中的部分特殊操作。

3.1 pbuf_alloc函数第一个参数分析

在网络中通信的数据报文,除了真正的数据段外,还包括了TCP/IP各层协议的报文头。如用户有特殊需求,要在应用层构建报文并直接通过网卡驱动发送,则需要申请pbuf结构的数据缓冲区带有各层偏移,如程序清单 3.1所示。

程序清单 3.1  pbuf_alloc第一个参数分析

typedef enum {
  PBUF_TRANSPORT,                                        /*  传输层报文头偏移          */
  PBUF_IP,                                               /*  IP层报文头偏移           */
  PBUF_LINK,                                             /*  链路层报文头偏移         */
  PBUF_RAW_TX,                                           /*  封装链路层偏移           */
  PBUF_RAW                                               /*  无偏移                 */
} pbuf_layer;

3.2 pbuf_alloc函数第三个参数分析

申请pbuf结构需要指定pbuf类型,原因是不同类型的pbuf申请内存的方式不同,如程序清单 3.2所示。

程序清单 3.2  pbuf_alloc第三个参数分析

typedef enum {
  PBUF_RAM,                                                 /*  内存堆分配             */
  PBUF_ROM,                                                 /*  指向ROM空间内数据      */
  PBUF_REF,                                                 /*  指向RAM空间内数据      */
  PBUF_POOL                                                 /*  内存池分配             */
} pbuf_type;

PBUF_RAM类型的pbuf主要通过内存堆分配得到,协议栈划分了一块空间用于申请PBUF_RAM类型的pbuf,划分的空间大小通过“libsylixos/SylixOS/config/net/net_perf_cfg.h”中的“LW_CFG_LWIP_MEM_SIZE”宏配置。

PBUF_REF和PBUF_ROM类型的pbuf基本相同,前者指向ROM空间内的某段数据,而后者指向RAM空间内的某段数据。PBUF_REF和PBUF_ROM类型的pbuf通过“libsylixos/SylixOS/config/net/net_perf_cfg.h”中的“LW_CFG_LWIP_NUM_PBUFS”宏配置在内存池中预分配pbuf的最大数量。

PBUF_POOL类型的pbuf通过内存池分配,这种类型的pbuf可以在极短时间内得到分配,在网卡驱动接收数据时,一般采用这种方式。协议栈会在内存池中预先分配适当数量和大小的内存空间,通过“libsylixos/SylixOS/config/net/net_perf_cfg.h”中的“LW_CFG_LWIP_POOL_SIZE和LW_CFG_LWIP_NUM_POOLS”宏配置。

3.3 PBUF_POOL类型pbuf申请流程

netdev_pbuf_alloc函数申请PBUF_POOL类型pbuf,若申请的缓冲区大于PBUF_POOL池中单个pbuf缓冲区长度,系统会分配多个固定大小的PBUF_POOL类型pbuf,并把这些pbuf链成一个链表,以满足用户的分配空间请求,如图 3.1所示。

SylixOS中netdev_pbuf_alloc函数分析

3.1  PBUF_POOL类型pbuf申请流程

4.实际应用

网卡驱动收到数据后,会调用netdev_pbuf_alloc函数申请pbuf结构,并将数据拷贝至pbuf。当有大量数据被网卡驱动接收时,可能会造成申请pbuf结构失败,原因是系统预分配的内存池中的pbuf结构已经全部被申请,还未被释放。可以尝试通过“libsylixos/SylixOS/config/net/net_perf_cfg.h”中的“LW_CFG_LWIP_POOL_SIZE和LW_CFG_LWIP_NUM_POOLS”宏配置增大pbuf缓冲区大小和数量解决pbuf结构申请失败问题。


分享标题:SylixOS中netdev_pbuf_alloc函数分析
分享地址:http://hbruida.cn/article/iiisej.html