lwip的記憶體管理

2021-08-18 06:18:26 字數 3548 閱讀 7912

至於lwip核心建立多少種pool依賴於使用者和系統配置,比如如果定義了巨集lwip_udp為1,那麼在編譯時與udp控制塊資料結構相關的記憶體池pool就會被建立(memp_udp_pcb),如果定義了巨集lwip_tcp為1,編譯時與tcp資料結構相關的記憶體池就會被建立(memp_tcp_pcb、memp_tcp_seg)等等!每種型別的pool大小都是固定的。使用者可以在lwipopts.h檔案中定義,lwip在opt.h中已經配置了預設值。

有6個與lwip記憶體池有關的全域性變數和資料結構:

memp_t、memp_tab、memp_sizes、memp_num、memp_desc和memp_memory。

memp_t為乙個列舉型別變數,用來給每個pool取個名字,或者說是編號。memp_t在檔案memp.h檔案中定義,定義如下:

這句**意思是:

遇到 lwip_mempool(name,num,size,desc) 換成 memp_##name

memp_tab為乙個全域性指標陣列,指向每類pool的第乙個pool,memp_tab在檔案memp.c檔案中定義,定義如下:

memp_sizes為乙個全域性陣列,用來記錄每個pool的大小,memp_sizes在檔案memp.c檔案中定義,定義如下:

編譯之後

const u16_t memp_sizes[memp_max] =

memp_sizes中儲存了每種型別pool的大小,這裡的大小都是進行了記憶體對齊的。

memp_num為乙個全域性陣列,用來記錄每類pool中pool的個數,memp_num在檔案memp.c檔案中定義,定義如下:

編譯之後

const u16_t memp_num[memp_max] =

;

上面的memp_num_raw_pcb、memp_num_udp_pcb等等都是由使用者定義的,用來記錄對應的pool的數量,使用者可以在lwipopts.h檔案中定義,lwip在opt.h中已經配置了預設值。

memp_desc為乙個全域性型指標陣列,指向每類pool的描述符 ,memp_desc在檔案memp.c檔案中定義,定義如下:

編譯之後

static const char *memp_desc[memp_max] =

;

memp_desc中的每個元素指向了乙個字串,這些字串在統計資訊輸出中可能用到。

memp_memory為乙個陣列,這個陣列才是真正的記憶體池!!!這個陣列 在檔案memp.c檔案中定義,定義如下:

編譯之後

static u8_t memp_memory

[ mem_alignment – 1

+((memp_num_raw_pcb) * (memp_size +

memp_align_size(sizeof(struct raw_pcb)) ))

+((memp_num_udp_pcb) * (memp_size +

memp_align_size(sizeof(struct udp_pcb)) ))

+((memp_num_tcp_pcb) * (memp_size +

memp_align_size(sizeof(struct tcp_pcb)) ))

……..

];

其中memp_size表示需要在每個pool頭部預留的空間,lwip中在某些特殊場合使用該空間中的值來對pool進行特殊處理,這裡不使用該項功能,所以memp_size為0,。如果使用到memp_size的話也需要對這個大小進行記憶體對齊!

使用記憶體池分配記憶體的優點在於速度快,效率高,不會產生記憶體碎片,但是缺點在於只能分配各種固定大小的記憶體空間,lwip必須實現知道使用者要使用哪些型別的pool,每種型別的pool數量,然後根據這個需求建立記憶體池。

lwip還提供了另外一種記憶體策略—記憶體堆,使用記憶體堆策略就可以隨便申請任意大小的記憶體了。但是這種方法效率和速度會有所下降。

使用記憶體堆策略的話使用者申請的記憶體大小有最小限制,所申請的記憶體大小不能小於min_size,lwip預設的min_size為12個位元組,在mem.c檔案中。該值使用者可以自行定義。

使用記憶體堆策略,其有點事記憶體浪費小,比較簡單,適合於小記憶體的管理,但是缺點就是如果頻繁的進行動態記憶體申請和釋放的話,可能會造成嚴重的記憶體碎片,如果碎片嚴重的話可能會導致記憶體分配失敗!

記憶體堆策略下的記憶體空間是陣列:ram_heap。在mem.c檔案中。

與記憶體堆有關的函式有3個:

mem_init()

mem_malloc()

mem_free()    

前面講的記憶體池(pool)和記憶體堆(heap)這兩個記憶體策略都是lwip預設的記憶體策略,lwip核心中大量的使用了這兩個策略,不過lwip也給我們提供了其他可選的記憶體策略。

(1)、當定義巨集mem_libc_malloc為1,那麼與記憶體堆相關的**就不會被編譯的,記憶體堆中的mem_malloc()和mem_free()就會被ansi c編譯器自帶的malloc()和free()替代。

(2)、當定義巨集memp_mem_malloc為1,那麼記憶體池檔案memp.c就不會被編譯。

(3)、當定義巨集mem_use_pools定義為1,那麼記憶體堆分配相關的函式及全域性變數不會被編譯,這個時候就用記憶體池分配方式來實現記憶體堆的的分配方式,因為記憶體池的分配策略效率很高。

但是(3)中的方法使用起來比較麻煩,需要在lwipopts.h中定義巨集mem_use_pools和mem_use_custom_pools都為1,還需要在另外乙個標頭檔案lwippools.h中開闢一些用於記憶體堆分配函式的記憶體池。

小議LWIP 記憶體對齊

每一種處理器都會有自己的記憶體對齊要求,這樣做的目的很大程度上是為了處理器讀取記憶體資料的效率,當然還有匯流排等因素的影響,具體的可以看一下為什麼要記憶體對齊 data alignment straighten up and fly right 我覺得寫得還不錯。好了,廢話不多說,接下來看一下lwi...

LwIP協議棧學習之動態記憶體管理

lwip 的動態記憶體管理機制可以有三種 動態記憶體堆分配策略可以有兩種實現方式 通過開闢乙個記憶體堆,然後通過模擬 c 執行時庫的記憶體分配策略來實現。通過動態記憶體池的方式來實現,也即動態記憶體堆分配函式通過簡單呼叫動態記憶體池 pool 分配函式來完成其功能,此時,需要在標頭檔案lwippoo...

LwIP 網路介面管理

netif 各種型別網路介面的抽象 netif.c netif.h netif.h 網路介面最大實體地址長度,這裡定義為乙太網網絡卡 mac 位址的長度 6 define netif max hwaddr len 6u 下面幾個巨集為網路介面屬性 狀態相關的巨集,主要用於描述 netif 中 fla...