netdev_pbuf_alloc是網卡驅動中的內存申請函數,申請一塊緩衝區用於存放網絡報文數據。網絡
netdev_pbuf_alloc函數以pbuf結構申請內存空間,如程序清單 2.1所示。函數
程序清單 2.1 pbuf結構spa
struct pbuf { struct pbuf *next; void *payload; u16_t tot_len; u16_t len; u8_t type; u8_t flags; u16_t ref; };
netdev_pbuf_alloc函數是pbuf_alloc函數的函數封裝,對外提供的函數接口只帶有一個參數用於指定申請的緩衝區大小。而pbuf_alloc函數有三個參數,分別是申請的pbuf數據緩衝區是否帶有偏移,數據緩衝區大小及緩衝區類型。在netdev_pbuf_alloc函數中,申請的pbuf結構緩衝區數據偏移固定爲0,緩衝區類型爲PBUF_POOL。netdev_pbuf_alloc函數傳入的第二個參數緩衝區大小在調用pbuf_alloc函數申請pbuf結構時會被增長一個reserve長度,用於協議棧中的部分特殊操做。.net
在網絡中通訊的數據報文,除了真正的數據段外,還包括了TCP/IP各層協議的報文頭。如用戶有特殊需求,要在應用層構建報文並直接經過網卡驅動發送,則須要申請pbuf結構的數據緩衝區帶有各層偏移,如程序清單 3.1所示。code
程序清單 3.1 pbuf_alloc第一個參數分析接口
typedef enum { PBUF_TRANSPORT, /* 傳輸層報文頭偏移 */ PBUF_IP, /* IP層報文頭偏移 */ PBUF_LINK, /* 鏈路層報文頭偏移 */ PBUF_RAW_TX, /* 封裝鏈路層偏移 */ PBUF_RAW /* 無偏移 */ } pbuf_layer;
申請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」宏配置。
netdev_pbuf_alloc函數申請PBUF_POOL類型pbuf,若申請的緩衝區大於PBUF_POOL池中單個pbuf緩衝區長度,系統會分配多個固定大小的PBUF_POOL類型pbuf,並把這些pbuf鏈成一個鏈表,以知足用戶的分配空間請求,如圖 3.1所示。
圖 3.1 PBUF_POOL類型pbuf申請流程
網卡驅動收到數據後,會調用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結構申請失敗問題。