日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LwIP 之六 详解动态内存管理 内存池(memp.c/h)

發布時間:2024/10/14 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LwIP 之六 详解动态内存管理 内存池(memp.c/h) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??該文主要是接上一部分LwIP 之 詳解動態內存管理 內存堆(mem.c/h),該部分許多內容需要用到上一篇的內容。該部分主要是詳細介紹LwIP中的動態內存池。整個內存池的實現相較于內存堆來說,還是麻煩點的。光是看源碼中那一堆宏定義就夠費勁!此外還有一點就是,該部分的文件結構也是挺有意思的,主要就是對于宏各種巧妙運用!
??LwIP的內存池實現對應的源碼文件主要就是memp.c/h。除此之外,還有兩個頭文件memp_prive.h和memp_std.h。
之前也說過,LwIP內存池的實現受制于兩個宏值MEMP_MEM_MALLOC和MEM_USE_POOLS的限制。在該部分的源碼文件中,仍然到處可見這兩個宏值。

memp_std.h

??該文件主要定義了LwIP內部的內存池,此外還通過#include "lwippools.h"的形式,將用戶自定義的內存池包含進來。其為LwIP內部使用的文件,外部應用程序不應該使用該文件。這個文件被故意包含多次,一次使用LWIP_MEMPOOL()的空定義來處理所有include,后續多次包含用來構建各種mem池列表。
??該文件比較有意思,其中的宏值定義全部依賴于宏LWIP_MEMPOOL(name,num,size,desc),這樣,只要外部提供的該宏值不同,則包含該文件后的源文件(通常為memp.h或memp_priv.h)在預處理后,就會產生不一樣的結果。這樣,就可以通過在不同的地方多次包含該文件(前面必定提供宏值MEMPOOL)以產生不同結果!下面來詳細分析一下該文件。
??該文件的第一部分其實就是定義了三個宏值(第一個由memp.h或memp_priv.h提供),這三個宏值也就對應了LwIP所定義的三種內存池:

  • MEMPOOL: 標準內存池(這個宏通常來自別的文件memp.h或memp_priv.h,通過包含該文件形式定義對應的東西)
  • MALLOC_MEMPOOL: 提供給mem.c中的mem_malloc使用的內存池。前面說過,LwIP的內存堆可以用內存池來實現(依賴于MEMPOOL)。
  • PBUF_MEMPOOL: LwIP的pbuf結構使用的內存池(依賴于MEMPOOL)。pbuf再后面介紹!

上面的宏值為簡寫,沒寫參數部分。后面就是使用以上三個宏值,來定義不同的內存池!
??該文件的第二部分部分就是定義上面定義的宏值,來具體定義各種LwIP內部使用的內存池。其他文件(memp.h或memp_priv.h)包含該文件的地方,通過提供不同的MEMPOOL,該部分將產生不同的結果。其中有個地方需要注意一下:

#if MEMP_USE_CUSTOM_POOLS #include "lwippools.h" #endif /* MEMP_USE_CUSTOM_POOLS */

通過以上代碼,將用戶自己定義的內存池引入進來。同時也不難看出,如果用戶配置了使用內存池,就必須要定義文件lwippools.h,,并且將自己需要定義的內存池放到該文件中。
??最后,將所有宏值進行反定義,這樣就可以保證多次包含時,不會出現宏的重復定義!

memp_prive.h

??該文件定義了內存池的基本結構等,同樣為LwIP內部使用的文件,外部應用程序不應該使用該文件。且該文件需要使用memp.h中定義枚舉值。因此,這個文件的使用位置比較特殊,如下圖

重點注意上圖中,高亮部分的注釋。下面詳細分析以下該文件。
??該文件的第一部分為MEMP_OVERFLOW_CHECK,其主要用來進行內存池的溢出檢查,這里不多做說明。
??接下來的第二大部分就是內存池各種結構的定義。首先第一個結構如下:

#if !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK struct memp {struct memp *next; /* 下一個鏈表 */ #if MEMP_OVERFLOW_CHECKconst char *file; /* 發生溢出時調用函數的文件名,mem_malloc調用者的文件 */int line; /* 發生溢出時調用函數的行號,mem_malloc調用者的行數 */ #endif /* MEMP_OVERFLOW_CHECK */ }; #endif /* !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK */

LwIP的內存池是通過鏈表來組織的。上面的結構就是鏈表的節點結構了!
??接下來是一個比較復雜的枚舉變量的定義。其實,這里面就定義了兩個枚舉變量MEMP_POOL_HELPER_START 和 MEMP_POOL_HELPER_END,后面的一堆東西就是給這兩個枚舉變量賦初值的。這其中就需要memp.h中定義的枚舉變量memp_t中的值。

#if MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS /* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ typedef enum {/* Get the first (via:MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/MEMP_POOL_HELPER_FIRST = ((u8_t) #define LWIP_MEMPOOL(name,num,size,desc) #define LWIP_MALLOC_MEMPOOL_START 1 #define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 #define LWIP_MALLOC_MEMPOOL_END #include "lwip/priv/memp_std.h") ,/* Get the last (via:MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */MEMP_POOL_HELPER_LAST = ((u8_t) #define LWIP_MEMPOOL(name,num,size,desc) #define LWIP_MALLOC_MEMPOOL_START #define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * #define LWIP_MALLOC_MEMPOOL_END 1 #include "lwip/priv/memp_std.h") } memp_pool_helper_t;

首先說一下這個枚舉變量是干啥的!之前曾經說過,LwIP的內存堆可以使用內存池來實現。那么為了實現該部分,內存池這里必須要提供必要的結構、接口來供內存堆實現時調用。其中,這個枚舉結構就是定義出了內存池枚舉memp_t中的用戶定義的供內存堆使用的內存池的枚舉界限!將這個枚舉各部分展開后,就是如下

#if MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS /* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ typedef enum {/* Get the first (via:MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)“MEMP_POOL_##size” 這個東西,就是之前定義的枚舉memp_t中 ,用戶自定義的內存池的枚舉值,結果一步步替換后就成該名*/MEMP_POOL_HELPER_FIRST = ((u8_t) #define LWIP_MEMPOOL(name,num,size,desc) #define LWIP_MALLOC_MEMPOOL_START 1 #define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 #define LWIP_MALLOC_MEMPOOL_END// #if MEMP_USE_CUSTOM_POOLS // #include "lwippools.h" // #endif /* MEMP_USE_CUSTOM_POOLS */ // /* 這里將其展開之后就是如下 */ LWIP_MALLOC_MEMPOOL_START LWIP_MALLOC_MEMPOOL(20, 256) -> MEMP_POOL_256 LWIP_MALLOC_MEMPOOL(10, 512) -> MEMP_POOL_512 LWIP_MALLOC_MEMPOOL(5, 1512) -> MEMP_POOL_1512 LWIP_MALLOC_MEMPOOL_END#undef LWIP_MEMPOOL #undef LWIP_MALLOC_MEMPOOL #undef LWIP_MALLOC_MEMPOOL_START #undef LWIP_MALLOC_MEMPOOL_END #undef LWIP_PBUF_MEMPOOL) , /*最終 MEMP_POOL_HELPER_START = 1*MEMP_POOL_256+0*MEMP_POOL_512+0*MEMP_POOL_1512 = MEMP_POOL_256*//* Get the last (via:MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) 結束值展開和上面一樣不再說明 */MEMP_POOL_HELPER_LAST = ((u8_t) #define LWIP_MEMPOOL(name,num,size,desc) #define LWIP_MALLOC_MEMPOOL_START #define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * #define LWIP_MALLOC_MEMPOOL_END 1 #include "lwip/priv/memp_std.h")/* 最終 MEMP_POOL_HELPER_LAST = 0 + MEMP_POOL_256 * 0 + MEMP_POOL_512 * 0 + MEMP_POOL_1512 * 1 = MEMP_POOL_1512 */ } memp_pool_helper_t;

最終,宏MEMP_POOL_HELPER_FIRST = MEMP_POOL_256,而宏MEMP_POOL_HELPER_LAST = MEMP_POOL_1512。
??在接下來就是內存池描述符的結構定義了,在LwIP1.4.1版本中,以下各部分都是獨立的,最新版中將其統一成了一個結構體。具體如下:

/** Memory pool descriptor */ struct memp_desc { #if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY/** Textual description */const char *desc; #endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY */ #if MEMP_STATS/** Statistics */struct stats_mem *stats; #endif/** Element size */u16_t size; #if !MEMP_MEM_MALLOC/** Number of elements */u16_t num;/** Base address */u8_t *base;/** First free element of each pool. Elements form a linked list. */struct memp **tab; #endif /* MEMP_MEM_MALLOC */ };

??該文件的最后一部分就是個接口的定義了,其實現均在memp.c文件中,后面會詳細的說明。

memp.h

??該文件主要就是定義以下內存池使用的宏,結構等,其中部分結構放在了memp_priv.h文件中,如果之前看過LwIP1.4.1的源碼就會知道,原來是沒有memp_priv.h文件的,所有結構都在memp.h中,最新的源碼進行結構調整。文件開始就是如下:

/* run once with empty definition to handle all custom includes in lwippools.h*/ #define LWIP_MEMPOOL(name,num,size,desc) /* 這個宏為空 */ #include "lwip/priv/memp_std.h" /* 其中的定義均是基于上面宏值得,也就成了空 */

結合memp_std.h不難發現,將各宏展開后其實就剩下兩句:

#if MEMP_USE_CUSTOM_POOLS #include "lwippools.h" #endif

其實,再將上面展開后,里面定義的內存池也是無效的,如果文件lwippools.h中有引入其他文件或結構是,這幾句唯一的作用就是將用戶自定義的內存池時,用到的各種東西引入進來。否則以上就會全部為空,啥也不剩!
??接下來是如下幾句,這個枚舉就是列出LwIP中定義的各種內存池的對應的枚舉值。

typedef enum { #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, /* ## 為連接符 且會忽略##前后的空格, 例如:a ## b 其實就是 ab */ #include "lwip/priv/memp_std.h"MEMP_MAX } memp_t;

這個用來為每個定義的內存池定義一個枚舉變量值。memp_std.h中通過使用宏值#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name,來定義各種枚舉值,簡單將宏值展開后,就是如下

typedef enum {/** A list of internal pools used by LWIP.** LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description)* creates a pool name MEMP_pool_name. description is used in stats.c*/ #if LWIP_RAWMEMP_RAW_PCB, #endif /* LWIP_RAW */#if LWIP_UDPMEMP_UDP_PCB, #endif /* LWIP_UDP */#if LWIP_TCPMEMP_TCP_PCB,MEMP_TCP_PCB_LISTEN,MEMP_TCP_SEG, #endif /* LWIP_TCP */#if LWIP_IPV4 && IP_REASSEMBLYMEMP_REASSDATA, #endif /* LWIP_IPV4 && IP_REASSEMBLY */ #if (IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)MEMP_FRAG_PBUF, #endif /* IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF || (LWIP_IPV6 && LWIP_IPV6_FRAG) */#if LWIP_NETCONN || LWIP_SOCKETMEMP_NETBUF,MEMP_NETCONN, #endif /* LWIP_NETCONN || LWIP_SOCKET */#if NO_SYS==0MEMP_TCPIP_MSG_API, #if LWIP_MPU_COMPATIBLEMEMP_API_MSG, #if LWIP_DNSMEMP_DNS_API_MSG, #endif #if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKINGMEMP_SOCKET_SETGETSOCKOPT_DATA, #endif #if LWIP_NETIF_APIMEMP_NETIFAPI_MSG, #endif #endif /* LWIP_MPU_COMPATIBLE */ #if !LWIP_TCPIP_CORE_LOCKING_INPUTMEMP_TCPIP_MSG_INPKT, #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ #endif /* NO_SYS==0 */#if LWIP_IPV4 && LWIP_ARP && ARP_QUEUEINGMEMP_ARP_QUEUE, #endif /* LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING */#if LWIP_IGMPMEMP_IGMP_GROUP, #endif /* LWIP_IGMP */#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOMMEMP_SYS_TIMEOUT, #endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */#if LWIP_DNS && LWIP_SOCKETMEMP_NETDB, #endif /* LWIP_DNS && LWIP_SOCKET */ #if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMICMEMP_LOCALHOSTLIST, #endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */#if LWIP_IPV6 && LWIP_ND6_QUEUEINGMEMP_ND6_QUEUE, #endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */#if LWIP_IPV6 && LWIP_IPV6_REASSMEMP_IP6_REASSDATA, #endif /* LWIP_IPV6 && LWIP_IPV6_REASS */#if LWIP_IPV6 && LWIP_IPV6_MLDMEMP_MLD6_GROUP, #endif /* LWIP_IPV6 && LWIP_IPV6_MLD *//** A list of pools of pbuf's used by LWIP.** LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description)* creates a pool name MEMP_pool_name. description is used in stats.c* This allocates enough space for the pbuf struct and a payload.* (Example: pbuf_payload_size=0 allocates only size for the struct)*/MEMP_PBUF,MEMP_PBUF_POOL,/** Allow for user-defined pools; this must be explicitly set in lwipopts.h* since the default is to NOT look for lwippools.h*/ // #if MEMP_USE_CUSTOM_POOLS // #include "lwippools.h" // /* 這里將其展開之后就是如下 */ // LWIP_MALLOC_MEMPOOL_START // LWIP_MALLOC_MEMPOOL(20, 256) -> MEMP_POOL_256 // LWIP_MALLOC_MEMPOOL(10, 512) -> MEMP_POOL_512 // LWIP_MALLOC_MEMPOOL(5, 1512) -> MEMP_POOL_1512 // LWIP_MALLOC_MEMPOOL_END // #endif /* MEMP_USE_CUSTOM_POOLS */ MEMP_POOL_256, MEMP_POOL_512, MEMP_POOL_1512,MEMP_MAX } memp_t;

接下來,就是#include "lwip/priv/memp_priv.h" ,這個文件的引用必須放在這里,因為其內部會使用上面的枚舉值(memp_t)。繼續是一些宏定義,其中比較重要的就是LWIP_MEMPOOL_DECLARE(name,num,size,desc),這個宏最終用來定義出各內存池!而這其中,根據用戶配置的宏值MEMP_MEM_MALLOC和MEM_USE_POOLS的不同,會有不同的定義。其中前者方式下比較簡單、后者則相對來說復雜一些!

??該文件的最后一部分就是個接口的定義了,其實現均在memp.c文件中,后面會詳細的說明。

memp.c

??該文件主要就針對上面各種定義的具體實現了,整個文件代碼并沒多少行,看起來還是比較簡單的。比較麻煩的就是上面對于宏函數的巧妙運用上。文件開頭是如下結構

#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) #include "lwip/priv/memp_std.h" /* 全局型指針數組,指向每類POOL的描述符 */ const struct memp_desc* const memp_pools[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, #include "lwip/priv/memp_std.h" };

這里就是定義所有內存池了。看起來非常簡單,但是真正展開各宏值才是比較麻煩的!再接下來就是具體的實現函數了,下面就以源碼注釋的形式進行說明(注意對于其中的調試用的函數或者安全性函數不進行說明)。

/*** Initialize custom memory pool.* Related functions: memp_malloc_pool, memp_free_pool** @param desc pool to initialize*/ void memp_init_pool(const struct memp_desc *desc) { #if MEMP_MEM_MALLOCLWIP_UNUSED_ARG(desc); #elseint i;struct memp *memp;*desc->tab = NULL;memp = (struct memp*)LWIP_MEM_ALIGN(desc->base); /* 將內存池起始空間進行對齊,這個宏在上一篇文章中有詳細介紹 *//* create a linked list of memp elements */for (i = 0; i < desc->num; ++i) { /* 將該類所有POOL組成鏈表的形式 */memp->next = *desc->tab;*desc->tab = memp; #if MEMP_OVERFLOW_CHECKmemp_overflow_init_element(memp, desc); #endif /* MEMP_OVERFLOW_CHECK *//* cast through void* to get rid of alignment warnings */memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size #if MEMP_OVERFLOW_CHECK+ MEMP_SANITY_REGION_AFTER_ALIGNED #endif);} #if MEMP_STATSdesc->stats->avail = desc->num; #endif /* MEMP_STATS */ #endif /* !MEMP_MEM_MALLOC */#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)desc->stats->name = desc->desc; #endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */ }/*** Initializes lwIP built-in pools.* Related functions: memp_malloc, memp_free** Carves out memp_memory into linked lists for each pool-type.*/ void memp_init(void) {u16_t i;/* 對每個定義的內存池進行初始化 */for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {memp_init_pool(memp_pools[i]); /* 初始化是根據文件開頭定義的內存池描述符(memp_pools數組)表進行的 */#if LWIP_STATS && MEMP_STATSlwip_stats.memp[i] = memp_pools[i]->stats; #endif}#if MEMP_OVERFLOW_CHECK >= 2/* check everything a first time to see if it worked */memp_overflow_check_all(); #endif /* MEMP_OVERFLOW_CHECK >= 2 */ }static void* #if !MEMP_OVERFLOW_CHECK do_memp_malloc_pool(const struct memp_desc *desc) #else do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) #endif {struct memp *memp;SYS_ARCH_DECL_PROTECT(old_level);/* 臨界保護區 */#if MEMP_MEM_MALLOCmemp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size));SYS_ARCH_PROTECT(old_level); #else /* MEMP_MEM_MALLOC */SYS_ARCH_PROTECT(old_level);/* 進入臨界區 */memp = *desc->tab; #endif /* MEMP_MEM_MALLOC */if (memp != NULL) { #if !MEMP_MEM_MALLOC #if MEMP_OVERFLOW_CHECK == 1memp_overflow_check_element_overflow(memp, desc);memp_overflow_check_element_underflow(memp, desc); #endif /* MEMP_OVERFLOW_CHECK */*desc->tab = memp->next; #if MEMP_OVERFLOW_CHECKmemp->next = NULL; #endif /* MEMP_OVERFLOW_CHECK */ #endif /* !MEMP_MEM_MALLOC */ #if MEMP_OVERFLOW_CHECKmemp->file = file;memp->line = line; #if MEMP_MEM_MALLOCmemp_overflow_init_element(memp, desc); #endif /* MEMP_MEM_MALLOC */ #endif /* MEMP_OVERFLOW_CHECK */LWIP_ASSERT("memp_malloc: memp properly aligned",((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); #if MEMP_STATSdesc->stats->used++;if (desc->stats->used > desc->stats->max) {desc->stats->max = desc->stats->used;} #endifSYS_ARCH_UNPROTECT(old_level);/* cast through u8_t* to get rid of alignment warnings */return ((u8_t*)memp + MEMP_SIZE);} else {LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc)); #if MEMP_STATSdesc->stats->err++; #endif}SYS_ARCH_UNPROTECT(old_level);/* 退出臨界區 */return NULL; }/*** Get an element from a custom pool.** @param desc the pool to get an element from** @return a pointer to the allocated memory or a NULL pointer on error*/ void * #if !MEMP_OVERFLOW_CHECK memp_malloc_pool(const struct memp_desc *desc) #else memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) #endif {LWIP_ASSERT("invalid pool desc", desc != NULL);if (desc == NULL) {return NULL;}#if !MEMP_OVERFLOW_CHECKreturn do_memp_malloc_pool(desc); #elsereturn do_memp_malloc_pool_fn(desc, file, line); #endif }/*** Get an element from a specific pool.** @param type the pool to get an element from** @return a pointer to the allocated memory or a NULL pointer on error*//* 分配過程是如果memp_tab[]數組中相應鏈表的指針為空,說明該類型的POOL已經沒有了,分配失敗;否則選擇鏈表中的第一個POOL,并在POOL最開始處預留出MEMP_SIZE(這里為0)的空間,最后將有效地址返回給函數調用者。*/ void * #if !MEMP_OVERFLOW_CHECK memp_malloc(memp_t type) #else memp_malloc_fn(memp_t type, const char* file, const int line) #endif {void *memp;LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;);#if MEMP_OVERFLOW_CHECK >= 2memp_overflow_check_all(); #endif /* MEMP_OVERFLOW_CHECK >= 2 */#if !MEMP_OVERFLOW_CHECKmemp = do_memp_malloc_pool(memp_pools[type]); #elsememp = do_memp_malloc_pool_fn(memp_pools[type], file, line); #endifreturn memp; }static void do_memp_free_pool(const struct memp_desc* desc, void *mem) {struct memp *memp;SYS_ARCH_DECL_PROTECT(old_level);LWIP_ASSERT("memp_free: mem properly aligned",((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);/* cast through void* to get rid of alignment warnings */memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);SYS_ARCH_PROTECT(old_level); /* 進入臨界區 */#if MEMP_OVERFLOW_CHECK == 1memp_overflow_check_element_overflow(memp, desc);memp_overflow_check_element_underflow(memp, desc); #endif /* MEMP_OVERFLOW_CHECK */#if MEMP_STATSdesc->stats->used--; #endif#if MEMP_MEM_MALLOCLWIP_UNUSED_ARG(desc);SYS_ARCH_UNPROTECT(old_level);mem_free(memp); #else /* MEMP_MEM_MALLOC */memp->next = *desc->tab;*desc->tab = memp;#if MEMP_SANITY_CHECKLWIP_ASSERT("memp sanity", memp_sanity(desc)); #endif /* MEMP_SANITY_CHECK */SYS_ARCH_UNPROTECT(old_level); /* 退出臨界區 */ #endif /* !MEMP_MEM_MALLOC */ }/*** Put a custom pool element back into its pool.** @param desc the pool where to put mem* @param mem the memp element to free*/ void memp_free_pool(const struct memp_desc* desc, void *mem) {LWIP_ASSERT("invalid pool desc", desc != NULL);if ((desc == NULL) || (mem == NULL)) {return;}do_memp_free_pool(desc, mem); }/*** Put an element back into its pool.** @param type the pool where to put mem* @param mem the memp element to free*//* 內存池釋放 */ void memp_free(memp_t type, void *mem) { #ifdef LWIP_HOOK_MEMP_AVAILABLEstruct memp *old_first; #endifLWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;);if (mem == NULL) {return;}#if MEMP_OVERFLOW_CHECK >= 2memp_overflow_check_all(); #endif /* MEMP_OVERFLOW_CHECK >= 2 */#ifdef LWIP_HOOK_MEMP_AVAILABLEold_first = *memp_pools[type]->tab; #endifdo_memp_free_pool(memp_pools[type], mem);#ifdef LWIP_HOOK_MEMP_AVAILABLEif (old_first == NULL) {LWIP_HOOK_MEMP_AVAILABLE(type);} #endif }

還有好多解釋沒完善的地方,后續用到在整理。。

總結

以上是生活随笔為你收集整理的LwIP 之六 详解动态内存管理 内存池(memp.c/h)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。