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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

LWIP再探----内存池管理

發(fā)布時間:2025/7/14 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LWIP再探----内存池管理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這這里是接上一篇內(nèi)存池管理部分的,這里如果讀者一打開memp.c的話會感覺特別那一理解原作者在干嘛,但是看懂了就明白原作者是怎么巧妙的使用了宏。廢話不多說先說了下我分析是一下宏的條件是

前提條件
MEMP_STATS = 0
MEMP_OVERFLOW_CHECK = 0

首先要去簡單的看下#include "lwip/priv/memp_std.h"文件的格式,只需要明白這個文件依賴LWIP_MEMPOOL(name,num,size,desc)這個宏,并且在文件結(jié)尾將宏清除。

因此出現(xiàn)底下的最難的兩塊

#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) #include "lwip/priv/memp_std.h"const struct memp_desc *const memp_pools[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, #include "lwip/priv/memp_std.h" };

先說第一個,繼續(xù)追LWIP_MEMPOOL_DECLARE的定義如下,看完繼續(xù)懵逼中。。。,但是不能慌一個個宏替換出來

#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \\LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \\static struct memp *memp_tab_ ## name; \\const struct memp_desc memp_ ## name = { \DECLARE_LWIP_MEMPOOL_DESC(desc) \LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \LWIP_MEM_ALIGN_SIZE(size), \(num), \memp_memory_ ## name ## _base, \&memp_tab_ ## name \};

里面相關(guān)宏的實(shí)現(xiàn)匯總?cè)缦?/p> #ifndef LWIP_DECLARE_MEMORY_ALIGNED #define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)] #endif#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) #define DECLARE_LWIP_MEMPOOL_DESC(desc)#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name)#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U))

最后就有這樣一個過程

#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \\LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \\static struct memp *memp_tab_ ## name; \\const struct memp_desc memp_ ## name = { \DECLARE_LWIP_MEMPOOL_DESC(desc) \LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \LWIP_MEM_ALIGN_SIZE(size), \(num), \memp_memory_ ## name ## _base, \&memp_tab_ ## name \};||\|/#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \memp_memory_RAW_PCB_base[(num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; \static struct memp *memp_tab_RAW_PCB; \const struct memp_desc memp_RAW_PCB = {\LWIP_MEM_ALIGN_SIZE(size), \(num), \memp_memory_RAW_PCB _base,\&memp_tab_ RAW_PCB\ };

然后就是這樣子的宏替換,此處未全部列舉

#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) #include "lwip/priv/memp_std.h"||\|/memp_memory_RAW_PCB_base[(num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; \static struct memp *memp_tab_RAW_PCB; const struct memp_desc memp_RAW_PCB = {“RAW_PCB”LWIP_MEM_ALIGN_SIZE(size), (num), memp_memory_RAW_PCB _base,&memp_tab_ RAW_PCB };memp_memory_UDP_PCB_base[(num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; \static struct memp *memp_tab_UDP_PCB; const struct memp_desc memp_UDP_PCB = {“UDP_PCB” LWIP_MEM_ALIGN_SIZE(size), (num), memp_memory_UDP_PCB _base,&memp_tab_UDP_PCB}; . . .

,同理理解到這里下面繼續(xù)第二個宏就是同理結(jié)果如下

const struct memp_desc *const memp_pools[MEMP_MAX] = { #define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, #include "lwip/priv/memp_std.h" };||\|/const struct memp_desc *const memp_pools[MEMP_MAX] = { &memp_RAW_PCB, &memp_UDP_PCB, . . . }

注意這里的MEMP_MAX是這樣來的

typedef enum { #define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, #include "lwip/priv/memp_std.h" MEMP_MAX } memp_t; | | \|/ typedef enum { MEMP_RAW_PCB, MEMP_UDP_PCB, . . . MEMP_MAX } memp_t;

然后這里還還需要了解一個結(jié)構(gòu)體的定義如下,

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 *//** 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_pools就將整個mempool的內(nèi)存串到了一個結(jié)構(gòu)體數(shù)組中。要注意此時每個memp_pools中的memp_desc結(jié)構(gòu)體中的memp_tab_UDP_PCB還只是一個指針的指針,并未有具體的實(shí)際意義。然后memp_init會進(jìn)行這一工作,去掉宏不編譯的部分
memp_init如下

void memp_init(void) {u16_t i;/* for every pool: */for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {memp_init_pool(memp_pools[i]);} }

就是循環(huán)調(diào)用memp_init_pool,接著看去掉宏簡化后的memp_init_pool

void memp_init_pool(const struct memp_desc *desc) {int 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) {memp->next = *desc->tab;*desc->tab = memp;memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size} }

到這里所有內(nèi)存池的定義和初始化已經(jīng)完成了借用野火的一張圖,初始化后的pool結(jié)構(gòu)如下

每一個類型的池最后由,tab將所有的空閑池串起來,組成一個內(nèi)存池單向鏈表。到此最難理解的部分已經(jīng)完了,接下來內(nèi)存池的內(nèi)存分配和釋放就是很簡單的內(nèi)容了。

內(nèi)存申請

void * memp_malloc(memp_t type){void *memp;// 取對應(yīng)內(nèi)存池的控制塊memp = do_memp_malloc_pool(memp_pools[type]);return memp; } //這個函數(shù)內(nèi)部實(shí)際上調(diào)用了 do_memp_malloc_pool簡化后如下, static void * do_memp_malloc_pool(const struct memp_desc *desc) {struct memp *memp;SYS_ARCH_DECL_PROTECT(old_level);SYS_ARCH_PROTECT(old_level);memp = *desc->tab;if (memp != NULL) {*desc->tab = memp->next;SYS_ARCH_UNPROTECT(old_level);/* cast through u8_t* to get rid of alignment warnings */return ((u8_t *)memp + MEMP_SIZE);} else {SYS_ARCH_UNPROTECT(old_level);}return NULL; }

因?yàn)閠ab是空閑pool的頭,所以內(nèi)存申請直接就是返回tab指向pool就可以了。同時內(nèi)存釋放就是將pool從新插入單向鏈表的操作了。具體簡化的代碼如下

內(nèi)存釋放

void memp_free(memp_t type, void *mem) {if (mem == NULL) {return;}do_memp_free_pool(memp_pools[type], mem);} //調(diào)用do_memp_free_pool static void do_memp_free_pool(const struct memp_desc *desc, void *mem) {struct memp *memp;SYS_ARCH_DECL_PROTECT(old_level);/* cast through void* to get rid of alignment warnings */memp = (struct memp *)(void *)((u8_t *)mem - MEMP_SIZE);SYS_ARCH_PROTECT(old_level);memp->next = *desc->tab;*desc->tab = memp;SYS_ARCH_UNPROTECT(old_level);}

現(xiàn)在LWIP的兩種內(nèi)存策略的實(shí)現(xiàn)方式,都已經(jīng)理解過了,其中內(nèi)存池的溢出檢測部分沒有說,但是已經(jīng)可以幫助我們使用LWIP了,作者設(shè)計(jì)兩種內(nèi)存策略是有他的設(shè)計(jì)初衷的,看了#include "lwip/priv/memp_std.h"文件就知道,內(nèi)存池的出現(xiàn)就是為一些特殊的長度固定的數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)的,他分配快速,釋放亦是,并且很定不會有內(nèi)存碎片,但是這還是一種空間換時間的做法,因?yàn)閮?nèi)存池申請函數(shù),支持如果當(dāng)前尺寸的pool用完了,可以分配更大的池。內(nèi)存堆就是用來應(yīng)對大小不定的內(nèi)存分配場合的,當(dāng)人LWIP支持用堆實(shí)現(xiàn)pool也支持用pool實(shí)現(xiàn)堆,同時還支持用戶池,這些功能都可以通過宏簡單 的配置具體如下

MEM_LIBC_MALLOC? 使用C庫

MEMP_MEM_MALLOC? 使用內(nèi)存堆替換內(nèi)襯池。

MEM_USE_POOLS? 使用內(nèi)存池替換內(nèi)存堆

MEMP_USE_CUSTOM_POOLS? ?使用用戶定義的內(nèi)存池,這個實(shí)現(xiàn)需要用戶提供一個文件lwippools.h,并按如下形式定義字節(jié)的內(nèi)存池,要求內(nèi)存池的大小要依次增大。

LWIP_MALLOC_MEMPOOL_START LWIP_MALLOC_MEMPOOL(20, 256) LWIP_MALLOC_MEMPOOL(10, 512) LWIP_MALLOC_MEMPOOL(5, 1512) LWIP_MALLOC_MEMPOOL_END

好了,到此LWIP的內(nèi)存管理部分算是簡單的學(xué)習(xí)了一下了,內(nèi)存管理完。

2019-06-16 17:58:42

?

轉(zhuǎn)載于:https://www.cnblogs.com/w-smile/p/11032337.html

總結(jié)

以上是生活随笔為你收集整理的LWIP再探----内存池管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。