<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于DWC_ether_qos的以太網驅動開發-LWIP的內存池介紹

嵌入式USB開發 ? 來源:嵌入式Lee ? 作者:嵌入式Lee ? 2023-09-07 08:45 ? 次閱讀

本文轉自公眾號,歡迎關注

https://mp.weixin.qq.com/s/mBoGSf_u9edFF01U_OZT9g

一.前言

lwIP為基礎結構提供了專用的內存池管理,比如netconn,protocol控制塊,包緩存等。在memp.c下實現。

LWIP的內存池有兩種方式實現,通過宏MEMP_MEM_MALLOC配置,默認opt.h中配置為0.

配置為1使用mem_malloc/mem_free mem.c

配置為0使用單獨實現memp.c。

我們這里重點講后者。

二.相關源碼

src/core/memp.c

src/include/lwip/memp.h

src/include/lwip/priv/memp_std.h

src/include/lwip/priv/memp_priv.h

三.源碼分析

3.1數據結構

內存池的關鍵數據結構是struct memp_desc對應內存池節點,一個類型的內存池是一個節點,

多個類型的內存池可以作為鏈表一起管理。

內存池最基本的數據結構是由宏LWIP_MEMPOOL_DECLARE定義的,

該宏在memp.h根據MEMP_MEM_MALLOC的配置實現為

#define LWIP_MEMPOOL_DECLARE(name,num,size,desc)

#define LWIP_MEMPOOL_DECLARE(name,num,size,desc)

前者是使用mem_malloc/mem_free實現內存池時使用,后者是單獨實現時使用,我們重點關注后者。

其中LWIP_DECLARE_MEMORY_ALIGNED可以用戶實現,如果用戶未定義,arch.h默認是

#ifndef LWIP_DECLARE_MEMORY_ALIGNED

即定義了一個數組variable_name,其大小是LWIP_MEM_ALIGN_BUFFER(size)

LWIP_MEM_ALIGN_BUFFER可以用戶實現,如果用戶未定義,arch.h中默認為

#ifndef LWIP_MEM_ALIGN_BUFFER

即人為的放大了,保證對齊之后始終能保證有足夠size的空間。

比如size是8,但是數組的基地址則可能是任意地址,比如是0x0001,要保證地址4字節對齊,

那么只能往后移動實際用的地址是0x0004,那么前面就浪費了3字節,此時8+(4-1)多分配3字節則浪費了這3字節也能保證剩余8字節可用8+(4-1)-3=8。

如果地址是0x0002則浪費2字節,可用8+(4-1)-2>8大于2字節,其他情況類似。

其中MEM_ALIGNMENT在opt中默認為1,用戶在lwipopts.h中可以配置。

繼續來看宏LWIP_MEMPOOL_DECLARE_STATS_INSTANCE和LWIP_MEMPOOL_DECLARE_STATS_REFERENCE,memp_priv.h中

如果定義了宏MEMP_STATS即使能統計信息,則LWIP_MEMPOOL_DECLARE_STATS_INSTANCE定義了結構體變量static struct stats_mem name;

LWIP_MEMPOOL_DECLARE_STATS_REFERENCE即&name,該變量地址

否則都是空

#if MEMP_STATS

其中stats.h中truct stats_mem如下

/** Memory stats */

繼續看DECLARE_LWIP_MEMPOOL_DESC,memp_priv.h中

如果定義了宏LWIP_DEBUG,MEMP_OVERFLOW_CHECK,LWIP_STATS_DISPLAY三者之一,實際就是成員賦值為desc,否則為空。

#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY

繼續看LWIP_MEM_ALIGN_SIZE,在arch.h中默認實現,即向上對齊,MEM_ALIGNMENT對齊必須是2的指數。

#ifndef LWIP_MEM_ALIGN_SIZE

最終LWIP_MEMPOOL_DECLARE(name,num,size,desc)展開后為

u8_t memp_memory_name_base[LWIP_MEM_ALIGN_BUFFER(((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size))))]

static struct stats_mem memp_stats_name;

static struct memp*memp_tab_name;

const struct memp_desc memp_name= {

desc,

&memp_stats_name,

LWIP_MEM_ALIGN_SIZE(size),

num,

memp_memory_ name_base,

&memp_tab_name

};

即定義一個數組作為存儲,一個統計變量,一個static struct memp指針變量,一個結構變量static struct memp。

其中struct memp

#if !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK

其中struct memp_desc

/** Memory pool descriptor */

3.2內存池接口

LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description")

即上面數據結構說明的,使用該宏定義節點相關存儲數組,變量等。

LWIP_MEMPOOL_INIT(my_private_pool) ->memp_init_pool

將節點的存儲鏈表形式串起來。

*desc->tab指向最后一個item。

void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool);->memp_malloc_pool

從鏈表中取出一個item。

LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem);->memp_free_pool

Item插入到鏈表中

這里管理內存池實際可以用上述的鏈表形式,也可以用bitmap形式。

上述用鏈表形式每次malloc(出鏈表),free(入鏈表)都是堆鏈表尾,*desc->tab操作,執行時間固定。

而bitmap需要使用for循環去查詢空閑bit執行時間不固定,當然也可以使用類似ucOS優先級調度的查表法來優化。

四.內部使用的內存池

數據結構中分析了LWIP_MEMPOOL_DECLARE宏,實際就是定義內存節點相關的變量(存儲數組,統計變量,描述結構等)

用戶可以直接使用內存池接口。

而lwip內部也使用了內存池進行管理,見memp.c/memp.h

4.1內部使用內存池

memp.h中

/* run once with empty definition to handle all custom includes in lwippools.h */

第一個#include "lwip/priv/memp_std.h"前因為LWIP_MEMPOOL為空,所以include memp_std.h進來所有的LWIP_MEMPOOL為空,此時相當于只是include進來memp_std.h中包含的頭文件。

后一個#include "lwip/priv/memp_std.h"前LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,

所以include memp_std.h后相當于,定義了MEMP_xxx的枚舉

展開就是(當然要對應的宏使能才會有)

typedef enum {

RAW_PCB_RAW_PCB,

UDP_PCB_UDP_PCB,

......

MEMP_MAX

} memp_t;

注意每次memp_std.h中都undef了相關宏,所以不影響后續使用。

這里是一個小的編程技巧,一個頭文件不同的宏配置下展開為不同的內容。

而memp.c中

#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)

第一個包含memp_std.h 根據LWIP_MEMPOOL_DECLARE,定義了各個內存池節點

后一個memp_std.h則根據LWIP_MEMPOOL(name,num,size,desc) & name展開

即定義了一個結構體數組,數組的成員即上面定義的內存池節點。

const struct memp_desc *const memp_pools[MEMP_MAX] = {

&RAW_PCB,

......

};

所有使用到內建內存池總結如下

4.2內部使用內存池接口

以下都是調用內存池接口,不再贅述。

memp_free

memp_free_pool

memp_malloc

memp_malloc_pool

memp_init

五.堆使用內存池實現

前面我們看到定義宏MEMP_MEM_MALLOC,memp.c內存池可以使用mem.c堆實現.

反過來定義宏MEM_USE_POOLS,mem.c也可以用memp.c內存池實現.所以可以看出LWIP的堆管理實現方式比較靈活的,可以根據實際應用配置。

在opt.h中MEM_USE_POOLS是默認配置為0的,可以在lwipopts.h中修改配置。

#if !defined MEM_USE_POOLS || defined __DOXYGEN__

如果MEMP_USE_CUSTOM_POOLS配置為1,則MEMP_USE_CUSTOM_POOLS也要配置為1

此時

memp_std.h中

/*

可以看出,用戶必須提供lwippools.h文件,申明對應的內存池節點。

即在原來memp_t和memp_pools的基礎上后面繼續添加節點。

內容如下

LWIP_MALLOC_MEMPOOL_START

此時mem_malloc則從

memp_pools中

MEMP_POOL_FIRST~MEMP_POOL_LAST處

搜搜,找到有節點有空閑空間,大小滿足所需大小的即止。

即如下獲取MEMP_POOL_HELPER_FIRST和MEMP_POOL_HELPER_LAST

#if MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS

六.總結

內存池適合分配大小固定的動態內存分配,比如用于協議包等的緩存等;

算法簡單,執行時間固定,比較可靠。但是其存儲是單獨分配的靜態數組,相當于需要固定分配一部分空間,不管對應的程序運行還是不運行,比較浪費空間。

當然也可以定義宏MEMP_MEM_MALLOC使用mem_malloc堆的方式實現,而mem_malloc進一步可以配置使用LWIP的實現還是使用系統的malloc(配置宏MEM_LIBC_MALLOC)。

此時和系統堆共用,這樣存儲利用率更高。

LWIP內部實現了堆和內存池管理可以直接使用,也可以配置使用系統的堆管理,非常靈活,移植性也非常好。

wKgaomT5Jw6AbNkLAAPYEkmgmX8781.png

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 以太網
    +關注

    關注

    40

    文章

    5145

    瀏覽量

    167025
  • 內存
    +關注

    關注

    8

    文章

    2794

    瀏覽量

    73037
  • 驅動開發
    +關注

    關注

    0

    文章

    129

    瀏覽量

    12021
收藏 人收藏

    評論

    相關推薦

    基于DWC_ether_qos以太網驅動開發-MAC幀格式介紹

    本文轉自公眾號,歡迎關注 基于DWC_ether_qos以太網驅動開發-MAC幀格式介紹 (qq.com) 一.前言 ? 在
    的頭像 發表于 08-30 09:23 ?1416次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-MAC幀格式<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網驅動開發-MDIO驅動編寫與測試

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-MDIO驅動編寫與測試 一.前言
    的頭像 發表于 08-30 09:37 ?2667次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-MDIO<b class='flag-5'>驅動</b>編寫與測試

    基于DWC_ether_qos以太網驅動開發-描述符鏈表介紹

    本文轉自公眾號歡迎關注 一.描述符概述 1.0 前言 對于DWC Ethernet QoS驅動的編寫來說,初始化完成之后,核心操作就是DMA的描述符鏈表配置(linked list
    的頭像 發表于 08-30 09:39 ?3113次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-描述符鏈表<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網驅動開發-數據流驗證過程

    轉自公眾號歡迎關注 https://mp.weixin.qq.com/s/klrHhaLMM_0W3FGVwHXFkA 基于DWC_ether_qos以太網驅動開發-數據流驗證過程
    的頭像 發表于 08-31 08:41 ?1313次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-數據流驗證過程

    基于DWC_ether_qos以太網驅動開發-收發驅動編寫與調試

    本文轉自公眾號,歡迎關注 基于DWC_ether_qos以太網驅動開發-收發驅動編寫與調試 (qq.com) https://mp.wei
    的頭像 發表于 09-05 08:47 ?1557次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-收發<b class='flag-5'>驅動</b>編寫與調試

    基于DWC_ether_qos以太網驅動開發-無OS環境移植LWIP

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-無OS環境移植LWIP (qq.com) https://mp.we
    的頭像 發表于 09-06 08:40 ?968次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-無OS環境移植<b class='flag-5'>LWIP</b>

    基于DWC_ether_qos以太網驅動開發-LWIP的堆管理介紹

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-LWIP的堆管理介紹 (
    的頭像 發表于 09-08 08:40 ?828次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的堆管理<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網驅動開發-LWIP的堆(內存池)未對齊導致問題的案例分享

    本文轉自公眾號歡迎關注 https://mp.weixin.qq.com/s/ErIa2ss2YZLGYbSwoJEzog 一.?前言 內存未對齊訪問問題這個已經是老生常談的問題了, 由于LWIP
    的頭像 發表于 09-09 08:44 ?1305次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的堆(<b class='flag-5'>內存</b>池)未對齊導致問題的案例分享

    基于DWC_ether_qos以太網驅動開發-RTOS環境移植LWIP與性能測試

    本文轉自公眾號,歡迎關注 基于DWC_ether_qos以太網驅動開發-RTOS環境移植LWIP與性能測試 (qq.com) https:
    的頭像 發表于 09-11 11:20 ?1312次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-RTOS環境移植<b class='flag-5'>LWIP</b>與性能測試

    基于DWC_ether_qos以太網驅動開發-LWIP在PC上進行開發調試

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-LWIP在PC上進行開發
    的頭像 發表于 09-11 08:40 ?1360次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>在PC上進行<b class='flag-5'>開發</b>調試

    基于DWC_ether_qos以太網驅動開發-LWIP的定時器模塊詳解

    一. 前言 LWIP的定時器模塊,實現了通用的軟件定時器,用于內部的周期事件處理,比如arp,tcp的超時等,用戶也可以使用。這一篇來分析該模塊的實現。 二.代碼分析 2.1源碼 源碼
    的頭像 發表于 09-18 09:33 ?1031次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的定時器模塊詳解

    基于DWC_ether_qos以太網驅動開發-LWIP的ARP模塊介紹

    TCP/IP通訊第一步需要先調通ARP,否則TCP/IP包都不知道MAC地址要發給誰。這一篇來基于LWIP的ARP實現進行相關的分析。
    的頭像 發表于 09-18 09:34 ?1204次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的ARP模塊<b class='flag-5'>介紹</b>

    設計軟件核心以太網服務質量數據手冊免費下載

    本文描述Synopsys設計軟件核心以太網服務質量DWC以太網QoS核心5.10A。DWC以太網
    發表于 10-23 08:00 ?15次下載
    設計軟件核心<b class='flag-5'>以太網</b>服務質量數據手冊免費下載

    基于DWC_ether_qos以太網驅動開發-包過濾

    以太網上數據非常多,如果所有數據都接收交給軟件去處理軟件負載會非常重,所以一般只需要接收發給自己的數據即可
    的頭像 發表于 09-02 09:19 ?1014次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-包過濾

    基于DWC_ether_qos以太網驅動開發-軟復位介紹與問題案例

    一般模塊都會有軟復位的功能,軟復位在驅動編寫中很重要。一般初始化時執行軟復位使得模塊進入確定的初始狀態以提高可靠性,異常時也可以重新初始化來恢復,所以軟復位在驅動中一般是必須要做的動作。
    的頭像 發表于 09-02 09:17 ?998次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-軟復位<b class='flag-5'>介紹</b>與問題案例
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>