LwIP之动态内存堆
生活随笔
收集整理的這篇文章主要介紹了
LwIP之动态内存堆
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?
內存堆其實就是一個數(shù)組。為了方便管理需要將內存堆首尾組織成內存塊,因此多分配的2?* SIZEOF_STRUCT_MEM大小的空間
/* 內存堆空間 */ static u8_t ram_heap[MEM_SIZE_ALIGNED + (2 * SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];動態(tài)內存堆會被組織成內存塊,用于管理內存的分配和釋放
/* 內存塊結構體 */ struct mem {/* 指向后一個內存塊 */mem_size_t next;/* 指向前一個內存塊 */mem_size_t prev;/* 內存塊是否被使用 1:被使用 0:未使用 */u8_t used; };?
初始化堆內存,將對內部組織成內存塊鏈表。
/* 內存堆初始化 */ void mem_init(void) {struct mem *mem;/* 內存堆地址 */ram = LWIP_MEM_ALIGN(ram_heap);/* 將內存堆首部組織成一個內存塊,該內存塊包含整個內存堆有效區(qū)域 */mem = (struct mem *)ram;mem->next = MEM_SIZE_ALIGNED;mem->prev = 0;mem->used = 0;/* 在內存堆尾部組織成一個內存塊 */ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED];ram_end->used = 1;ram_end->next = MEM_SIZE_ALIGNED;ram_end->prev = MEM_SIZE_ALIGNED;/* 更新地址最低的空閑內存塊 */lfree = (struct mem *)ram; }?
內存分配,從鏈表中找到一個合適的內存塊,分配給程序。將剩下的內存組織成新的內存塊,并掛接到鏈表。
/* 申請內存 */ void *mem_malloc(mem_size_t size) {mem_size_t ptr, ptr2;struct mem *mem, *mem2;/* 內存申請不能為0 */if (size == 0) {return NULL;}/* 申請大小字節(jié)對齊 */size = LWIP_MEM_ALIGN_SIZE(size);/* 申請大小最小12字節(jié) */if(size < MIN_SIZE_ALIGNED) {size = MIN_SIZE_ALIGNED;}/* 內存申請不能超過內存堆 */if (size > MEM_SIZE_ALIGNED) {return NULL;}/* 遍歷所有內存塊 */for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size; ptr = ((struct mem *)&ram[ptr])->next) {/* 內存塊地址 */mem = (struct mem *)&ram[ptr];/* 找出合適的內存塊 */if ((!mem->used) && (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) {/* 內存塊過大 */if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) {/* 將多出來的內存重新組織成內存塊 */ptr2 = ptr + SIZEOF_STRUCT_MEM + size;mem2 = (struct mem *)&ram[ptr2];mem2->used = 0;mem2->next = mem->next;mem2->prev = ptr;/* 當前內存塊標記為已使用,并將新內存塊插入鏈表 */mem->next = ptr2;mem->used = 1;if (mem2->next != MEM_SIZE_ALIGNED) {((struct mem *)&ram[mem2->next])->prev = ptr2;}} else {/* 當前內存塊標記為已使用 */mem->used = 1;}/* 當前內存塊為地址最低的空閑內存塊 */if (mem == lfree) {/* 更新地址最低的空閑內存塊 */while (lfree->used && lfree != ram_end) {lfree = (struct mem *)&ram[lfree->next];}}/* 返回內存地址 */return (u8_t *)mem + SIZEOF_STRUCT_MEM;}}return NULL; }?
釋放內存,將內存重新組織成內存塊插入鏈表。相鄰內存堆都空閑,需要合并。
/* 釋放內存 */ void mem_free(void *rmem) {struct mem *mem;if (rmem == NULL) {return;}/* 內存地址必須在內存堆中 */if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {return;}/* 通過內存地址找出內存塊結構體指針 */mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);/* 將內存塊標識為空閑 */mem->used = 0;/* 更新地址最低空閑塊 */if (mem < lfree) {lfree = mem;}/* 合并空閑塊 */plug_holes(mem); } /* 合并空閑塊 */ static void plug_holes(struct mem *mem) {struct mem *nmem;struct mem *pmem;/* 下一個內存塊 */nmem = (struct mem *)&ram[mem->next];/* 下一個內存塊未被使用,并且不是最后一個內存塊 */if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {/* 更新地址最低的空閑內存塊 */if (lfree == nmem) {lfree = mem;}/* 和后一個內存塊合并 */mem->next = nmem->next;((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;}/* 上一個空閑塊 */pmem = (struct mem *)&ram[mem->prev];/* 上一個內存塊未使用 */if (pmem != mem && pmem->used == 0) {/* 更新地址最低的空閑內存塊 */if (lfree == mem) {lfree = pmem;}/* 和上一個內存塊合并 */pmem->next = mem->next;((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;} }?
除了基本的分配和釋放,協(xié)議棧還mem_realloc函數(shù)和mem_calloc函數(shù)
mem_realloc函數(shù),能夠收縮內存,將原有的內存縮小。縮小的部分重新組織成內存塊,掛接到鏈表。
/* 收縮內存 */ void *mem_realloc(void *rmem, mem_size_t newsize) {mem_size_t size;mem_size_t ptr, ptr2;struct mem *mem, *mem2;/* 新內存大小字節(jié)對齊 */newsize = LWIP_MEM_ALIGN_SIZE(newsize);/* 內存大小最小12字節(jié) */if(newsize < MIN_SIZE_ALIGNED) {newsize = MIN_SIZE_ALIGNED;}/* 內存大小不能超過內存堆 */if (newsize > MEM_SIZE_ALIGNED) {return NULL;}/* 內存地址必須在內存堆中 */if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {return rmem;}/* 通過內存地址找出內存塊結構體指針 */mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);/* 內存在內存堆中的偏移量 */ptr = (u8_t *)mem - ram;/* 計算內存塊內存大小 */size = mem->next - ptr - SIZEOF_STRUCT_MEM;/* 只能縮小,不能擴展 */if (newsize > size) {return NULL;}/* 內存大小不變,直接返回 */if (newsize == size) {return rmem;}/* 下一個內存塊空閑 */mem2 = (struct mem *)&ram[mem->next];if(mem2->used == 0) {mem_size_t next;/* 將切割下來的內存和下一個內存塊合并 */next = mem2->next;ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;if (lfree == mem2) {lfree = (struct mem *)&ram[ptr2];}mem2 = (struct mem *)&ram[ptr2];mem2->used = 0;mem2->next = next;mem2->prev = ptr;mem->next = ptr2;if (mem2->next != MEM_SIZE_ALIGNED) {((struct mem *)&ram[mem2->next])->prev = ptr2;}} /* 下一個內存塊不空閑 */else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {/* 將切割下來的內存重新組織成內存塊 */ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;mem2 = (struct mem *)&ram[ptr2];if (mem2 < lfree) {lfree = mem2;}mem2->used = 0;mem2->next = mem->next;mem2->prev = ptr;mem->next = ptr2;if (mem2->next != MEM_SIZE_ALIGNED) {((struct mem *)&ram[mem2->next])->prev = ptr2;}}/* 返回內存指針 */return rmem; }mem_calloc函數(shù),申請內存的同時,將內存清空。
/* 申請內存并清零 */ void *mem_calloc(mem_size_t count, mem_size_t size) {void *p;p = mem_malloc(count * size);if (p) {memset(p, 0, count * size);}return p; }?
總結
以上是生活随笔為你收集整理的LwIP之动态内存堆的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 区块链将如何影响你的生活?链圈大佬、美图
- 下一篇: 我30岁了。现在开始编程,会不会太晚?