0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于DWC_ether_qos的以太網(wǎng)驅(qū)動開發(fā)-LWIP的內(nèi)存池介紹

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

本文轉(zhuǎn)自公眾號,歡迎關(guān)注

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

一.前言

lwIP為基礎(chǔ)結(jié)構(gòu)提供了專用的內(nèi)存池管理,比如netconn,protocol控制塊,包緩存等。在memp.c下實(shí)現(xiàn)。

LWIP的內(nèi)存池有兩種方式實(shí)現(xiàn),通過宏MEMP_MEM_MALLOC配置,默認(rèn)opt.h中配置為0.

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

配置為0使用單獨(dú)實(shí)現(xiàn)memp.c。

我們這里重點(diǎn)講后者。

二.相關(guān)源碼

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數(shù)據(jù)結(jié)構(gòu)

內(nèi)存池的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)是struct memp_desc對應(yīng)內(nèi)存池節(jié)點(diǎn),一個類型的內(nèi)存池是一個節(jié)點(diǎn),

多個類型的內(nèi)存池可以作為鏈表一起管理。

內(nèi)存池最基本的數(shù)據(jù)結(jié)構(gòu)是由宏LWIP_MEMPOOL_DECLARE定義的,

該宏在memp.h根據(jù)MEMP_MEM_MALLOC的配置實(shí)現(xiàn)為

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

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

前者是使用mem_malloc/mem_free實(shí)現(xiàn)內(nèi)存池時使用,后者是單獨(dú)實(shí)現(xiàn)時使用,我們重點(diǎn)關(guān)注后者。

其中LWIP_DECLARE_MEMORY_ALIGNED可以用戶實(shí)現(xiàn),如果用戶未定義,arch.h默認(rèn)是

#ifndef LWIP_DECLARE_MEMORY_ALIGNED

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

LWIP_MEM_ALIGN_BUFFER可以用戶實(shí)現(xiàn),如果用戶未定義,arch.h中默認(rèn)為

#ifndef LWIP_MEM_ALIGN_BUFFER

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

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

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

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

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

繼續(xù)來看宏LWIP_MEMPOOL_DECLARE_STATS_INSTANCE和LWIP_MEMPOOL_DECLARE_STATS_REFERENCE,memp_priv.h中

如果定義了宏MEMP_STATS即使能統(tǒng)計信息,則LWIP_MEMPOOL_DECLARE_STATS_INSTANCE定義了結(jié)構(gòu)體變量static struct stats_mem name;

LWIP_MEMPOOL_DECLARE_STATS_REFERENCE即&name,該變量地址

否則都是空

#if MEMP_STATS

其中stats.h中truct stats_mem如下

/** Memory stats */

繼續(xù)看DECLARE_LWIP_MEMPOOL_DESC,memp_priv.h中

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

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

繼續(xù)看LWIP_MEM_ALIGN_SIZE,在arch.h中默認(rèn)實(shí)現(xiàn),即向上對齊,MEM_ALIGNMENT對齊必須是2的指數(shù)。

#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

};

即定義一個數(shù)組作為存儲,一個統(tǒng)計變量,一個static struct memp指針變量,一個結(jié)構(gòu)變量static struct memp。

其中struct memp

#if !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK

其中struct memp_desc

/** Memory pool descriptor */

3.2內(nèi)存池接口

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

即上面數(shù)據(jù)結(jié)構(gòu)說明的,使用該宏定義節(jié)點(diǎn)相關(guān)存儲數(shù)組,變量等。

LWIP_MEMPOOL_INIT(my_private_pool) ->memp_init_pool

將節(jié)點(diǎn)的存儲鏈表形式串起來。

*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插入到鏈表中

這里管理內(nèi)存池實(shí)際可以用上述的鏈表形式,也可以用bitmap形式。

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

而bitmap需要使用for循環(huán)去查詢空閑bit執(zhí)行時間不固定,當(dāng)然也可以使用類似ucOS優(yōu)先級調(diào)度的查表法來優(yōu)化。

四.內(nèi)部使用的內(nèi)存池

數(shù)據(jù)結(jié)構(gòu)中分析了LWIP_MEMPOOL_DECLARE宏,實(shí)際就是定義內(nèi)存節(jié)點(diǎn)相關(guān)的變量(存儲數(shù)組,統(tǒng)計變量,描述結(jié)構(gòu)等)

用戶可以直接使用內(nèi)存池接口。

而lwip內(nèi)部也使用了內(nèi)存池進(jìn)行管理,見memp.c/memp.h

4.1內(nèi)部使用內(nèi)存池

memp.h中

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

第一個#include "lwip/priv/memp_std.h"前因?yàn)長WIP_MEMPOOL為空,所以include memp_std.h進(jìn)來所有的LWIP_MEMPOOL為空,此時相當(dāng)于只是include進(jìn)來memp_std.h中包含的頭文件。

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

所以include memp_std.h后相當(dāng)于,定義了MEMP_xxx的枚舉

展開就是(當(dāng)然要對應(yīng)的宏使能才會有)

typedef enum {

RAW_PCB_RAW_PCB,

UDP_PCB_UDP_PCB,

......

MEMP_MAX

} memp_t;

注意每次memp_std.h中都undef了相關(guān)宏,所以不影響后續(xù)使用。

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

而memp.c中

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

第一個包含memp_std.h 根據(jù)LWIP_MEMPOOL_DECLARE,定義了各個內(nèi)存池節(jié)點(diǎn)

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

即定義了一個結(jié)構(gòu)體數(shù)組,數(shù)組的成員即上面定義的內(nèi)存池節(jié)點(diǎn)。

const struct memp_desc *const memp_pools[MEMP_MAX] = {

&RAW_PCB,

......

};

所有使用到內(nèi)建內(nèi)存池總結(jié)如下

4.2內(nèi)部使用內(nèi)存池接口

以下都是調(diào)用內(nèi)存池接口,不再贅述。

memp_free

memp_free_pool

memp_malloc

memp_malloc_pool

memp_init

五.堆使用內(nèi)存池實(shí)現(xiàn)

前面我們看到定義宏MEMP_MEM_MALLOC,memp.c內(nèi)存池可以使用mem.c堆實(shí)現(xiàn).

反過來定義宏MEM_USE_POOLS,mem.c也可以用memp.c內(nèi)存池實(shí)現(xiàn).所以可以看出LWIP的堆管理實(shí)現(xiàn)方式比較靈活的,可以根據(jù)實(shí)際應(yīng)用配置。

在opt.h中MEM_USE_POOLS是默認(rèn)配置為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文件,申明對應(yīng)的內(nèi)存池節(jié)點(diǎn)。

即在原來memp_t和memp_pools的基礎(chǔ)上后面繼續(xù)添加節(jié)點(diǎn)。

內(nèi)容如下

LWIP_MALLOC_MEMPOOL_START

此時mem_malloc則從

memp_pools中

MEMP_POOL_FIRST~MEMP_POOL_LAST處

搜搜,找到有節(jié)點(diǎn)有空閑空間,大小滿足所需大小的即止。

即如下獲取MEMP_POOL_HELPER_FIRST和MEMP_POOL_HELPER_LAST

#if MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS

六.總結(jié)

內(nèi)存池適合分配大小固定的動態(tài)內(nèi)存分配,比如用于協(xié)議包等的緩存等;

算法簡單,執(zhí)行時間固定,比較可靠。但是其存儲是單獨(dú)分配的靜態(tài)數(shù)組,相當(dāng)于需要固定分配一部分空間,不管對應(yīng)的程序運(yùn)行還是不運(yùn)行,比較浪費(fèi)空間。

當(dāng)然也可以定義宏MEMP_MEM_MALLOC使用mem_malloc堆的方式實(shí)現(xiàn),而mem_malloc進(jìn)一步可以配置使用LWIP的實(shí)現(xiàn)還是使用系統(tǒng)的malloc(配置宏MEM_LIBC_MALLOC)。

此時和系統(tǒng)堆共用,這樣存儲利用率更高。

LWIP內(nèi)部實(shí)現(xiàn)了堆和內(nèi)存池管理可以直接使用,也可以配置使用系統(tǒng)的堆管理,非常靈活,移植性也非常好。

wKgaomT5Jw6AbNkLAAPYEkmgmX8781.png

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 以太網(wǎng)
    +關(guān)注

    關(guān)注

    40

    文章

    5424

    瀏覽量

    171701
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3025

    瀏覽量

    74042
  • 驅(qū)動開發(fā)
    +關(guān)注

    關(guān)注

    0

    文章

    130

    瀏覽量

    12077
收藏 人收藏

    評論

    相關(guān)推薦

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-MAC幀格式介紹

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-MDIO驅(qū)動編寫與測試

    本文轉(zhuǎn)自公眾號歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-MDIO驅(qū)動編寫與測試 一.前言
    的頭像 發(fā)表于 08-30 09:37 ?3767次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-MDIO<b class='flag-5'>驅(qū)動</b>編寫與測試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-描述符鏈表介紹

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-數(shù)據(jù)流驗(yàn)證過程

    轉(zhuǎn)自公眾號歡迎關(guān)注 https://mp.weixin.qq.com/s/klrHhaLMM_0W3FGVwHXFkA 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-數(shù)據(jù)流驗(yàn)證過程
    的頭像 發(fā)表于 08-31 08:41 ?2053次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-數(shù)據(jù)流驗(yàn)證過程

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-收發(fā)驅(qū)動編寫與調(diào)試

    本文轉(zhuǎn)自公眾號,歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-收發(fā)驅(qū)動編寫與調(diào)試 (qq.com) https://mp.wei
    的頭像 發(fā)表于 09-05 08:47 ?2342次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-收發(fā)<b class='flag-5'>驅(qū)動</b>編寫與調(diào)試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-無OS環(huán)境移植LWIP

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的堆管理介紹

    本文轉(zhuǎn)自公眾號歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的堆管理介紹 (
    的頭像 發(fā)表于 09-08 08:40 ?1319次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-<b class='flag-5'>LWIP</b>的堆管理<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的堆(內(nèi)存)未對齊導(dǎo)致問題的案例分享

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-RTOS環(huán)境移植LWIP與性能測試

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP在PC上進(jìn)行開發(fā)調(diào)試

    本文轉(zhuǎn)自公眾號歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP在PC上進(jìn)行開發(fā)
    的頭像 發(fā)表于 09-11 08:40 ?2040次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-<b class='flag-5'>LWIP</b>在PC上進(jìn)行<b class='flag-5'>開發(fā)</b>調(diào)試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的定時器模塊詳解

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的ARP模塊介紹

    TCP/IP通訊第一步需要先調(diào)通ARP,否則TCP/IP包都不知道MAC地址要發(fā)給誰。這一篇來基于LWIP的ARP實(shí)現(xiàn)進(jìn)行相關(guān)的分析。
    的頭像 發(fā)表于 09-18 09:34 ?1916次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-<b class='flag-5'>LWIP</b>的ARP模塊<b class='flag-5'>介紹</b>

    以太網(wǎng)Lwip例程

    以太網(wǎng)Lwip例程
    發(fā)表于 12-06 16:53 ?28次下載
    <b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>Lwip</b>例程

    設(shè)計軟件核心以太網(wǎng)服務(wù)質(zhì)量數(shù)據(jù)手冊免費(fèi)下載

    本文描述Synopsys設(shè)計軟件核心以太網(wǎng)服務(wù)質(zhì)量DWC以太網(wǎng)QoS核心5.10A。DWC以太網(wǎng)
    發(fā)表于 10-23 08:00 ?16次下載
    設(shè)計軟件核心<b class='flag-5'>以太網(wǎng)</b>服務(wù)質(zhì)量數(shù)據(jù)手冊免費(fèi)下載

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-包過濾

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