首页 > 编程知识 正文

malloc函数动态分配数组,malloc能分配多大内存

时间:2023-05-04 02:55:08 阅读:9483 作者:2757

由于源代码是美丽外套内存池的动态内存分配,实际使用中发现分配速度不够快,因此我们优化了分配算法。

在malloc.c中有两种分配方法。 被遮罩的内容会在漂亮的外套基础上添加内存块大小的占用空间,然后直接跳过。 这样,在遇到较大的存储器空间块时可以大幅节省for循环的次数。 很容易理解,缺点是如果中途存在多个未利用区域,for循环的次数就会浪费。

第二种方法是首先计算所需的内存块大小,直接去查找相应大小的块,然后推迟是否为空。 如果不是全空,则基于该非空而向前偏移相应大小来顺序计算的方法可以比第一个更快地找到需求存储器块。

举个例子,内存池的状态如下。 红色的地方被占用,绿色的地方没有被占用。 然后,内存块大小必须为7

用漂亮的外套做第一个程序,需要for循环5 6 3 6 2 6 7=35次

如果使用掩码算法,则需要for循环5 1 3 1 2 1 7=20次

第二种方法需要第一个for到86,然后浪费了两次for循环。 之后,从1次到81,从1次到75,从1次到69,再从2次到71,再到64,最后几五次,申请成功了。 整个过程需要1 2 1 1 1 2 1 5=14次。

第二种方法是内存块越大,块越碎,优于第一种。

当然,上述两种方法对连续小块内存分配速度仍然无可奈何。

malloc.h

# ifndef _ malloc _ h # define _ malloc _ h # include ' API _ define _ all.h ' # ifndef null # define null0# endeng defing definemem _ alloc _ table _ size mem _ max _ size/mem _ block _ size/dfinemem _ block _ div5# elif mem _ block _ CK div efin emem _ block _ div2# elif mem _ block _ size==2# definemem _ block _ div1# endiftypedefunsignedcharu 8; typedef unsigned short u16; typedef unsigned int u32; //内存管理控制器struct_m_mallco_dev{void(*init ) ) void ); //u8 (初始化) ) void ); //内存使用率u8 *membase; //内存池u16 *memmap; //内存管理状态表u8 memrdy; //内存管理是否就绪}; extern struct _ m _ mall co _ devmallco _ dev; 在mallco.c中定义voidmymemset(void*s、u8 c、u32 count ); //内存voidmymemcpy(void*des,void *src,u32 n )设置; //复制内存voidmem_init(void )//内存管理初始化函数U32mem_malloc(U32size ); //内存分配U8mem_free(U32offset; //内存释放U8mem_Perused(void ); //获取内存使用率//用户调用函数void__myfree(void*ptr ); //内存释放#definemyfree(x ) ) (__myfree ) x ); x=NULL; (void*mymalloc ) u32size; //内存分配void*myrealloc(void*ptr,u32 size ); //重新分配内存#endif mallc.c

#include 'malloc.h'//内存池(4字节对齐)/*_align )4) */u8 membase[MEM_MAX_SIZE]; //内部SRAM内存池//内存管理表u 16 memmapbase [ mem _ alloc _ table _ size ]; //内部SRAM内存池MAP//内存管理参数constu 32 memtblsize=mem _ alloc _ table _ size; //内存表大小constu 32 me mblk size=mem _ block _ size; //存储器块大小const u32 memsize=MEM_MAX_SIZE; //存储器总容量#if Use_uCOS 0OS_SEM MALLOC_SEM; #endif//内存管理控制器struct _ m _ mall co _ devmallco _ dev={ mem _ init,//内存初始化mem_perused,//内存使用率

membase, //内存池 memmapbase, //内存管理状态表 0, //内存管理未就绪};//复制内存//*des:目的地址//*src:源地址//n:需要复制的内存长度(字节为单位)void mymemcpy(void *des, void *src, u32 n){ u8 *xdes = des; u8 *xsrc = src; while (n--) *xdes++ = *xsrc++;}//设置内存//*s:内存首地址//c :要设置的值//count:需要设置的内存大小(字节为单位)void mymemset(void *s, u8 c, u32 count){ u8 *xs = s; while (count--) *xs++ = c;}//内存管理初始化//memx:所属内存块void mem_init(void){ mymemset(mallco_dev.memmap, 0, memtblsize * 2); //内存状态表数据清零 mymemset(mallco_dev.membase, 0, memsize); //内存池所有数据清零 mallco_dev.memrdy = 1; //内存管理初始化OK OS_ERR err; CPU_SR cpu_sr = 0u; OS_CRITICAL_ENTER(); //创建一个信号量 OSSemCreate((OS_SEM *)&MALLOC_SEM, (CPU_CHAR *)"MALLOC_SEM", (OS_SEM_CTR)1, (OS_ERR *)&err); OS_CRITICAL_EXIT();}//获取内存使用率//memx:所属内存块//返回值:使用率(0~100)u8 mem_perused(void){ u32 used = 0; u32 i; for (i = 0; i < memtblsize; i++) { if (mallco_dev.memmap[i]) used++; } return (used * 100) / (memtblsize);}//内存分配(内部调用)//memx:所属内存块//size:要分配的内存大小(字节)//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址u32 mem_malloc(u32 size){ signed long offset = 0; u16 nmemb = 0; //需要的内存块数 u16 cmemb = 0; //连续空内存块数 u32 i = 0; if (!mallco_dev.memrdy) mallco_dev.init(); //未初始化,先执行初始化 if (size == 0) return 0XFFFFFFFF; //不需要分配 OS_ERR err; OSSemPend(&MALLOC_SEM, 0, OS_OPT_PEND_BLOCKING, 0, &err); //请求信号量 nmemb = size >> MEM_BLOCK_DIV; //获取需要分配的连续内存块数 if (size % memblksize) nmemb++; // for (offset = memtblsize - 1; offset >= 0; offset--) //搜索整个内存控制区 // { // if (!mallco_dev.memmap[offset]) // cmemb++; //连续空内存块数增加 // else // { // cmemb = 0; //连续内存块清零 // if (offset >= mallco_dev.memmap[offset]) // offset -= (mallco_dev.memmap[offset] - 1); //当内存块占用的大小 // else // break; /*如果不够减,说明内存池已经不够用了*/ // } // if (cmemb == nmemb) //找到了连续nmemb个空内存块 // { // for (i = 0; i < nmemb; i++) //标注内存块非空 // { // mallco_dev.memmap[offset + i] = nmemb; // } // OSSemPost(&MALLOC_SEM, OS_OPT_POST_1, &err); //发送信号量 // return (offset * memblksize); //返回偏移地址 // } // } if (memtblsize > nmemb) { offset = memtblsize - nmemb; for (i = 0; i + cmemb < nmemb;) { if (mallco_dev.memmap[offset + i]) //内存块不空 { if (offset + i >= nmemb) //即offset + i一定大于等于一 { if (mallco_dev.memmap[offset + i - 1] == mallco_dev.memmap[offset + i]) //说明落点在连续已被占有内存块内 { if (offset + i > mallco_dev.memmap[offset + i]) offset = offset + i - mallco_dev.memmap[offset + i]; else break; } else { offset = offset + i - nmemb; } cmemb = i; i = 0; } else break; //剩余大小已经不够分配了 } else i++; } cmemb += i; if (cmemb == nmemb) { for (i = 0; i < nmemb; i++) //标注内存块非空 { mallco_dev.memmap[offset + i] = nmemb; } OSSemPost(&MALLOC_SEM, OS_OPT_POST_1, &err); //发送信号量 return (offset * memblksize); //返回偏移地址 } } OSSemPost(&MALLOC_SEM, OS_OPT_POST_NONE, &err); //发送信号量 return 0XFFFFFFFF; //未找到符合分配条件的内存块}//释放内存(内部调用)//memx:所属内存块//offset:内存地址偏移//返回值:0,释放成功;1,释放失败;u8 mem_free(u32 offset){ int i; if (!mallco_dev.memrdy) //未初始化,先执行初始化 { mallco_dev.init(); return 1; //未初始化 } if (offset < memsize) //偏移在内存池内. { int index = offset / memblksize; //偏移所在内存块号码 int nmemb = mallco_dev.memmap[index]; //内存块数量 for (i = 0; i < nmemb; i++) //内存块清零 { mallco_dev.memmap[index + i] = 0; } return 0; } else return 2; //偏移超区了.}//释放内存(外部调用)//memx:所属内存块//ptr:内存首地址void __myfree(void *ptr){ u32 offset; if (ptr == NULL) return; //地址为0. offset = (u32)ptr - (u32)mallco_dev.membase; mem_free(offset); //释放内存}//分配内存(外部调用)//memx:所属内存块//size:内存大小(字节)//返回值:分配到的内存首地址.void *mymalloc(u32 size){ u32 offset = mem_malloc(size); if (offset == 0XFFFFFFFF) return NULL; else return (void *)((u32)mallco_dev.membase + offset);}//重新分配内存(外部调用)//memx:所属内存块//*ptr:旧内存首地址//size:要分配的内存大小(字节)//返回值:新分配到的内存首地址.void *myrealloc(void *ptr, u32 size){ u32 offset; offset = mem_malloc(size); if (offset == 0XFFFFFFFF) return NULL; else { mymemcpy((void *)((u32)mallco_dev.membase + offset), ptr, size); //拷贝旧内存内容到新内存 myfree(ptr); //释放旧内存 return (void *)((u32)mallco_dev.membase + offset); //返回新内存首地址 }}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。