SylixOS中netdev_pbuf_alloc函数分析
netdev_pbuf_alloc是网卡驱动中的内存申请函数,申请一块缓冲区用于存放网络报文数据。
2.pbuf结构分析netdev_pbuf_alloc函数以pbuf结构申请内存空间,如程序清单 2.1所示。
程序清单 2.1 pbuf结构
structpbuf{structpbuf*next;void*payload;u16_ttot_len;u16_tlen;u8_ttype;u8_tflags;u16_tref;};
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第一个参数分析
typedefenum{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第三个参数分析
typedefenum{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所示。
图 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结构申请失败问题。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。