当前位置: 首页 > news >正文

莒县网站建设公司网站开通

莒县网站建设,公司网站开通,指数函数求导,慕枫网络科技有限公司目录 1、内存堆控制 1.1 内存堆控制器 1.2 内存块节点 1.3 内存堆管理 2、内存堆初始化 2.1 初始化接口 2.2 初始化示例 2.3 源码分析 3、内存堆操作 3.1 内存块申请 3.1.1 相关接口 3.1.2 原理分析 3.1.3 示例分析 3.1.4 代码分析 3.2 内存块伸缩 3.2.1 相关…目录 1、内存堆控制 1.1 内存堆控制器    1.2 内存块节点 1.3 内存堆管理 2、内存堆初始化 2.1 初始化接口 2.2 初始化示例 2.3 源码分析 3、内存堆操作 3.1 内存块申请 3.1.1 相关接口 3.1.2 原理分析 3.1.3 示例分析 3.1.4 代码分析 3.2 内存块伸缩 3.2.1 相关接口 3.2.2 原理分析 3.2.3 示例分析 3.2.4 源码分析 3.3 内存快释放 3.3.1 相关接口 3.3.2 原理分析 3.3.3 示例分析 3.3.4 源码分析 本章讲解RT_Thread Nano实时操作系统的动态内存(内存堆)部分RT-Thread提供三种动态内存管理算法小堆内存管理算法、堆内存管理方法、SLAB内存管理算法。小堆内存管理模块主要针对系统资源比较少一般用于小于2M内存空间的系统堆内存可以应用于多块不连续的内存堆SLAB内存管理模块则主要是在系统资源比较丰富时提供了一种近似多内存池管理算法的快速算法。三种内存管理模块在系统运行时只能选择其中之一或者完全不使用动态堆内存管理器。 三种管理模块提供的API接口完全相同小堆内存管理算法接口在mem.c堆内存管理方法在memheap.c文件中定义SLAB内存管理模块在slab.c文件中定义。 内存管理方法适用场景宏定义设置接口定义位置小堆内存小于2M内存空间 RT_USING_HEAP RT_USING_SMALL_MEM mem.c堆内存多块不连续的内存堆 RT_USING_MEMHEAP_AS_HEAP RT_USING_MEMTRACE memheap.cSLAB系统资源比较丰富 RT_USING_HEAP RT_USING_SLAB slab.c 本章主要讲解静态小堆内存管理算法其特点是内存利用率高适用于小存储空间。 本章基于RT_Thread Nano V3.1.5版本分析 1、内存堆控制 1.1 内存堆控制器    内存堆控制器由一些全局变量定义如下所示 static rt_uint8_t *heap_ptr; // 内存堆首地址 static struct heap_mem *heap_end; // 内存堆尾部节点 static struct heap_mem *lfree; // 指向最低地址空闲块节点,用于管理空闲内存块 static struct rt_semaphore heap_sem; // 内存信号,用于临界资源权限保护 static rt_size_t mem_size_aligned; // 对齐后小堆内存总大小 static rt_size_t used_mem; // 记录已使用字节数 static rt_size_t max_mem; // 记录已使用字节数的最大值 1.2 内存块节点 内存堆链表节点如下所示宏定义ARCH_CPU_64BIT表示系统内核为64位。 struct heap_mem {rt_uint16_t magic; /*内存块标志字默认0x1ea0*/rt_uint16_t used; /*0表示内存块空闲1表示内存块被申请*/#ifdef ARCH_CPU_64BITrt_uint32_t resv;#endifrt_size_t next, prev; /*next表示上个内存块节点的相对位置prev表示下个内存块节点的相对位置*//*内存监视使能*/#ifdef RT_USING_MEMTRACE#ifdef ARCH_CPU_64BITrt_uint8_t thread[8]; /* 记录线程名称*/#elsert_uint8_t thread[4]; /* 记录线程名称*/#endif#endif }; 1.3 内存堆管理 小堆内存中通过一个双向链表管理内存块每个内存块首定义一个节点节点按照地址从小到大顺序双向连接。 内存节点参数next, prev非指针变量而是表示节点地址相对于堆首地址heap_ptr的偏移通过偏移定位和连接上下内存块节点位置例如一内存节点指针struct heap_mem *mem其下个相邻节点位置为heap_ptr[mem-next]上个相邻节点位置为heap_ptr[mem-prev]同时可计算出其内存块大小为 size(heap_ptr(mem-next)-(char*)mem-sizeof(struct heap_mem)); 空闲内存块指针*lfree指向地址最低的空闲内存块内存申请时从lfree指向位置开始向高地址遍历所有内存块直至找到合适的空闲内存块。当内存块释放后需要重新判断和定位lfree位置。 系统内核为64位时最小内存堆默认24字节否则默认12字节。最小长度可调。 #ifdef ARCH_CPU_64BIT #define MIN_SIZE 24 #else #define MIN_SIZE 12 #endif 2、内存堆初始化 小内存堆通过全局变量管理将内存区对齐后首尾各定义一个内存块节点堆首内存节点为空闲内存块节点堆尾节点属性是已使用将2个节点双向连接并将空闲内存块指针指向堆首节点。 2.1 初始化接口 /*** 系统堆初始化.* param begin_addr 系统堆起始地址* param end_addr 系统堆结束地址*/ void rt_system_heap_init(void *begin_addr, void *end_addr) 2.2 初始化示例 代码示例 unsigned char heap[1024*1024];rt_system_heap_init(heap,heapsizeof(heap)); 内存结构图示初始化完成后lfree指向首节点heap_end指向尾部节点收尾节单向链接。已使用字节数used_mem为0已使用字节数的最大值max_mem为0。 2.3 源码分析 /*** 系统堆初始化.* param begin_addr 系统堆起始地址* param end_addr 系统堆结束地址*/ void rt_system_heap_init(void *begin_addr, void *end_addr) {struct heap_mem *mem;/*内存堆首尾地址对齐,默认4字节对齐*/ rt_ubase_t begin_align RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE);rt_ubase_t end_align RT_ALIGN_DOWN((rt_ubase_t)end_addr, RT_ALIGN_SIZE);RT_DEBUG_NOT_IN_INTERRUPT;/*内存堆大小检验*/if ((end_align (2 * SIZEOF_STRUCT_MEM)) ((end_align - 2 * SIZEOF_STRUCT_MEM) begin_align)){/* 有效内存大小 */mem_size_aligned end_align - begin_align - 2 * SIZEOF_STRUCT_MEM;}else{rt_kprintf(mem init, error begin address 0x%x, and end address 0x%x\n,(rt_ubase_t)begin_addr, (rt_ubase_t)end_addr);return;}/* 内存头 */heap_ptr (rt_uint8_t *)begin_align;/* 调试代码*/RT_DEBUG_LOG(RT_DEBUG_MEM, (mem init, heap begin address 0x%x, size %d\n,(rt_ubase_t)heap_ptr, mem_size_aligned));/* 初始化内存头节点next链接尾部节点位置 */mem (struct heap_mem *)heap_ptr;mem-magic HEAP_MAGIC;mem-next mem_size_aligned SIZEOF_STRUCT_MEM;// 指向内存相对位置(数组下标),非指针mem-prev 0;mem-used 0;/*记录线程名称INIT*/ #ifdef RT_USING_MEMTRACErt_mem_setname(mem, INIT); #endif/*初始化内存堆尾部节点*/heap_end (struct heap_mem *)heap_ptr[mem-next];heap_end-magic HEAP_MAGIC;heap_end-used 1;heap_end-next mem_size_aligned SIZEOF_STRUCT_MEM;/*与尾部链表连接*/heap_end-prev mem_size_aligned SIZEOF_STRUCT_MEM; #ifdef RT_USING_MEMTRACErt_mem_setname(heap_end, INIT); #endif/*初始化内存权限信号*/rt_sem_init(heap_sem, heap, 1, RT_IPC_FLAG_FIFO);/* 初始化空闲块指针,指向堆首节点 */lfree (struct heap_mem *)heap_ptr; } 3、内存堆操作 内存堆操作可以分为内存申请、内存伸缩、内存释放。 3.1 内存块申请 3.1.1 相关接口 接口rt_malloc仅申请一定大小的内存并不进行初始化所以申请的内存数据值不确定。接口rt_calloc审请内存后会初始化为0。可以类比于C库的malloc、calloc接口。 /*动态内存申请接口,size--申请内存大小申请成功后返回内存块首地址否则返回Null*/ void *rt_malloc(rt_size_t size)/*动态内存申请接口,count--申请内存单元个数size--单个单元大小 内存申请完成后初始化为0,申请成功后返回内存块首地址否则返回NULL*/ void *rt_calloc(rt_size_t count, rt_size_t size) 3.1.2 原理分析 内存控制块申请是从最低地址空闲内存块节点lfree指向的位置开始向高地址遍历所有内存块直至找到满足申请大小的空闲内存块将该内存块标记为已使用如果该内存块比较大从该内存块中切割出所需的内存剩余部分形成新的内存块并定义新的内存块节点插入到内存块双向链表中。 3.1.3 示例分析 unsigned char heap[1024*1024]; // 初始化调用 rt_system_heap_init(heap,heapsizeof(heap)); // 线程1调用,假设线程名称Led1 void Thread1() {char *p1rt_malloc(1200); } // 线程2调用,假设线程名称Led2 void Thread1() {char *p2rt_malloc(1000); } 3.1.4 代码分析 /*动态内存申请基础接口*/ void *rt_malloc(rt_size_t size) {rt_size_t ptr, ptr2;struct heap_mem *mem, *mem2;if (size 0) return RT_NULL;RT_DEBUG_NOT_IN_INTERRUPT;/*调试代码,长度是否对齐判断, */if (size ! RT_ALIGN(size, RT_ALIGN_SIZE))RT_DEBUG_LOG(RT_DEBUG_MEM, (malloc size %d, but align to %d\n,size, RT_ALIGN(size, RT_ALIGN_SIZE)));elseRT_DEBUG_LOG(RT_DEBUG_MEM, (malloc size %d\n, size));/*长度对齐,默认4字节 */size RT_ALIGN(size, RT_ALIGN_SIZE);/*分配长度size超过可用内存长度,返回失败*/if (size mem_size_aligned){RT_DEBUG_LOG(RT_DEBUG_MEM, (no memory\n));return RT_NULL;}/* 数据块长度容错 */if (size MIN_SIZE_ALIGNED)size MIN_SIZE_ALIGNED;/* 获取信号,阻塞方式为永久阻塞 */rt_sem_take(heap_sem, RT_WAITING_FOREVER);/*根据相对位置,遍历空闲链表,即从空闲表头开始遍历一直找到符合大小的控制块*/for (ptr (rt_uint8_t *)lfree - heap_ptr;ptr mem_size_aligned - size;ptr ((struct heap_mem *)heap_ptr[ptr])-next){/*取节点*/mem (struct heap_mem *)heap_ptr[ptr];/*判断内存块属性,未使用且大小满足size*/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;/* 设置新节点 create mem2 struct */mem2 (struct heap_mem *)heap_ptr[ptr2];mem2-magic HEAP_MAGIC;mem2-used 0;mem2-next mem-next;mem2-prev ptr;#ifdef RT_USING_MEMTRACE/*内存监视使能*/rt_mem_setname(mem2, );#endif/*按照地址顺序 插入节点and insert it between mem and mem-next */mem-next ptr2;mem-used 1;/**/if (mem2-next ! mem_size_aligned SIZEOF_STRUCT_MEM){((struct heap_mem *)heap_ptr[mem2-next])-prev ptr2;} #ifdef RT_MEM_STATS/*记录当前使用内存和最大使用内存*/used_mem (size SIZEOF_STRUCT_MEM);if (max_mem used_mem)max_mem used_mem; #endif}/* 不需要分割内存块 */else{/*设置为已使用*/mem-used 1; #ifdef RT_MEM_STATS/*记录当前使用内存和最大使用内存*/used_mem mem-next - ((rt_uint8_t *)mem - heap_ptr);if (max_mem used_mem) max_mem used_mem; #endif}/* 设置新节点标志字 set memory block magic */mem-magic HEAP_MAGIC; #ifdef RT_USING_MEMTRACE/*内存监视,记录线程名称*/if (rt_thread_self())rt_mem_setname(mem, rt_thread_self()-name);elsert_mem_setname(mem, NONE); #endif/*lfree指向的节点已被分配,调整空闲链表指针*/if (mem lfree){/* 指向下一个未被分配的内存块 */while (lfree-used lfree ! heap_end)lfree (struct heap_mem *)heap_ptr[lfree-next];/*断言*/RT_ASSERT(((lfree heap_end) || (!lfree-used)));}/*释放信号*/rt_sem_release(heap_sem);/*断言*/RT_ASSERT((rt_ubase_t)mem SIZEOF_STRUCT_MEM size (rt_ubase_t)heap_end);RT_ASSERT((rt_ubase_t)((rt_uint8_t *)mem SIZEOF_STRUCT_MEM) % RT_ALIGN_SIZE 0);RT_ASSERT((((rt_ubase_t)mem) (RT_ALIGN_SIZE - 1)) 0);/*调试代码*/RT_DEBUG_LOG(RT_DEBUG_MEM,(allocate memory at 0x%x, size: %d\n,(rt_ubase_t)((rt_uint8_t *)mem SIZEOF_STRUCT_MEM),(rt_ubase_t)(mem-next - ((rt_uint8_t *)mem - heap_ptr))));RT_OBJECT_HOOK_CALL(rt_malloc_hook,(((void *)((rt_uint8_t *)mem SIZEOF_STRUCT_MEM)), size));/* 返回块地址 */return (rt_uint8_t *)mem SIZEOF_STRUCT_MEM;}}rt_sem_release(heap_sem);return RT_NULL; }void *rt_calloc(rt_size_t count, rt_size_t size) {void *p;/* 申请内存大小size */p rt_malloc(count * size);/* 将申请的内存初始化为0 */if (p)rt_memset(p, 0, count * size);return p; } 3.2 内存块伸缩 3.2.1 相关接口 接口rt_realloc可以将已申请的内存大小进行调整或新申请一块内存。可以类比于C库的realloc接口。         /*动态内存长度伸缩,rmem--内存块首地址newsize--内存块新长度申请成功后返回内存块首地址否则返回NULL*/ void *rt_realloc(void *rmem, rt_size_t newsize) 3.2.2 原理分析 使用rt_realloc分配或调整内存块分以下几种情况newsize先进行对齐 1newsize对齐后为0直接释放内存块。 2内存块rmem未被分配直接按照newsize对齐后大小分配内存等同于rt_malloc(newsize)。 3rmem已被分配当newsize对齐后小于等于原内存块大小时可以对原内存块进行部分释放若newsize与原内存块差不足以划分一个新内存块时维持原内存结构不变。若足以划分一个新内存块时则划分出新的空闲内存块进行释放。 4rmem已被分配当newsize对齐后大于原内存块大小时则根据newsize重新申请内存并将原内存的数据复制到新内存块并释放原内存块。 3.2.3 示例分析 3.2.4 源码分析 void *void *rt_realloc(void *rmem, rt_size_t newsize) {rt_size_t size;rt_size_t ptr, ptr2;struct heap_mem *mem, *mem2;void *nmem;RT_DEBUG_NOT_IN_INTERRUPT;/*新尺寸对齐,默认4字节 */newsize RT_ALIGN(newsize, RT_ALIGN_SIZE);/*新尺寸过大,返回失败*/if (newsize mem_size_aligned){RT_DEBUG_LOG(RT_DEBUG_MEM, (realloc: out of memory\n));return RT_NULL;}/*新尺寸为0,释放内存块*/else if (newsize 0){rt_free(rmem);return RT_NULL;}/* rmem 未被分配,直接按照newsize大小分配内存 */if (rmem RT_NULL)return rt_malloc(newsize);/*获取信号权限*/rt_sem_take(heap_sem, RT_WAITING_FOREVER);/*内存块容错*/if ((rt_uint8_t *)rmem (rt_uint8_t *)heap_ptr ||(rt_uint8_t *)rmem (rt_uint8_t *)heap_end){/* 释放信号 */rt_sem_release(heap_sem);return rmem;}/*获取当前内存块节点*/mem (struct heap_mem *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM);/*新旧大小相同,直接释放信号后返回原内存块首地址*/ptr (rt_uint8_t *)mem - heap_ptr;size mem-next - ptr - SIZEOF_STRUCT_MEM;if (size newsize){/*释放信号*/rt_sem_release(heap_sem);return rmem;}/*新长度小于原长度并且满足划分新块的条件*/if (newsize SIZEOF_STRUCT_MEM MIN_SIZE size){/* 划分新内存块 */ #ifdef RT_MEM_STATSused_mem - (size - newsize); #endif/*设置新内存块节点*/ptr2 ptr SIZEOF_STRUCT_MEM newsize;mem2 (struct heap_mem *)heap_ptr[ptr2];mem2-magic HEAP_MAGIC;mem2-used 0;mem2-next mem-next;mem2-prev ptr;/*设置线程名称*/ #ifdef RT_USING_MEMTRACErt_mem_setname(mem2, ); #endifmem-next ptr2;if (mem2-next ! mem_size_aligned SIZEOF_STRUCT_MEM){((struct heap_mem *)heap_ptr[mem2-next])-prev ptr2;}/*调整空闲内存块指针*/if (mem2 lfree){/* the splited struct is now the lowest */lfree mem2;}/**/plug_holes(mem2);/*释放信号*/rt_sem_release(heap_sem);return rmem;}/*新长度大于原长度*//*释放信号*/ rt_sem_release(heap_sem);/* 重新分配内存 */nmem rt_malloc(newsize);if (nmem ! RT_NULL) /* check memory */{/*原内存区数据复制到新内存区然后释放原内存*/rt_memcpy(nmem, rmem, size newsize ? size : newsize);rt_free(rmem);}return nmem; }3.3 内存快释放 3.3.1 相关接口 /** 释放内存块,rmem指向内存块首地址*/ void rt_free(void *rmem) 3.3.2 原理分析 使用rt_free释放内存块 1设置内存块节点为空闲状态。 2如果下个相邻内存块为空闲状态则合并内存块将下个内存块的节点从链表删除。 3如果上个相邻内存块为空闲状态则合并内存块将当前内存块的节点从链表删除。 3.3.3 示例分析 3.3.4 源码分析 /** 释放内存块*/ void rt_free(void *rmem) {struct heap_mem *mem;if (rmem RT_NULL)return;RT_DEBUG_NOT_IN_INTERRUPT;/*断言*/RT_ASSERT((((rt_ubase_t)rmem) (RT_ALIGN_SIZE - 1)) 0);RT_ASSERT((rt_uint8_t *)rmem (rt_uint8_t *)heap_ptr (rt_uint8_t *)rmem (rt_uint8_t *)heap_end);/*执行钩子*/RT_OBJECT_HOOK_CALL(rt_free_hook, (rmem));/*地址检查*/if ((rt_uint8_t *)rmem (rt_uint8_t *)heap_ptr ||(rt_uint8_t *)rmem (rt_uint8_t *)heap_end){RT_DEBUG_LOG(RT_DEBUG_MEM, (illegal memory\n));return;}/* 获取当前内存块节点*/mem (struct heap_mem *)((rt_uint8_t *)rmem-SIZEOF_STRUCT_MEM);/*调试代码*/RT_DEBUG_LOG(RT_DEBUG_MEM,(release memory 0x%x, size: %d\n,(rt_ubase_t)rmem,(rt_ubase_t)(mem-next - ((rt_uint8_t *)mem - heap_ptr))));/* 获取内存信号权限 */rt_sem_take(heap_sem, RT_WAITING_FOREVER);/* 检查内存块节点*/if (!mem-used || mem-magic ! HEAP_MAGIC){rt_kprintf(to free a bad data block:\n);rt_kprintf(mem: 0x%08x, used flag: %d, magic code: 0x%04x\n, mem, mem-used, mem-magic);}/*断言,检查内存块节点*/RT_ASSERT(mem-used);RT_ASSERT(mem-magic HEAP_MAGIC);/*修改节点修改为未使用*/mem-used 0;mem-magic HEAP_MAGIC; #ifdef RT_USING_MEMTRACE/*复归线程名称为空格*/rt_mem_setname(mem, ); #endif/*调整空闲头部lfree指向地址最低的空闲控制块*/if (mem lfree){lfree mem;}#ifdef RT_MEM_STATS/*计算已使用内存*/used_mem - (mem-next - ((rt_uint8_t *)mem - heap_ptr)); #endif/* 合并内存块,前后内存块空闲判断*/plug_holes(mem);/*释放信号*/rt_sem_release(heap_sem); }/* 合并内存块,前后内存块空闲判断*/ static void plug_holes(struct heap_mem *mem) {struct heap_mem *nmem;struct heap_mem *pmem;/*断言*/RT_ASSERT((rt_uint8_t *)mem heap_ptr);RT_ASSERT((rt_uint8_t *)mem (rt_uint8_t *)heap_end);RT_ASSERT(mem-used 0);/* 判断下一个内存块如果是空闲块则合并 */nmem (struct heap_mem *)heap_ptr[mem-next];if (mem ! nmem nmem-used 0 (rt_uint8_t *)nmem ! (rt_uint8_t *)heap_end){/*纠正空闲节点lfreelfree指向地址最低的空闲内存块*/ if (lfree nmem){lfree mem;}/*删除下一个内存块节点*/mem-next nmem-next;((struct heap_mem *)heap_ptr[nmem-next])-prev (rt_uint8_t *)mem - heap_ptr;}/* 判断上一个内存块如果是空闲块则合并 */pmem (struct heap_mem *)heap_ptr[mem-prev];if (pmem ! mem pmem-used 0){/* 纠正空闲节点lfreelfree指向地址最低的空闲内存块 */if (lfree mem){lfree pmem;}/*删除当前节点*/pmem-next mem-next;((struct heap_mem *)heap_ptr[mem-next])-prev (rt_uint8_t *)pmem - heap_ptr;} }
http://www.dnsts.com.cn/news/8088.html

相关文章:

  • 辽宁平台网站建设公司高端购物网站
  • 一家专做灯的网站招聘大连有什么好玩的地方
  • 兄弟网络(西安网站建设制作公司)成都推广团队
  • 北京国都建设集团网站网站搜索框怎么做
  • 模板免费下载网站ppt一键优化
  • 徐州做网站xlec小企业网站模板
  • 广州公司注册网站官网wordpress 会员下载
  • 全国建设部官方网站亚马逊雨林简介
  • 做网站链接怎么弄wordpress 充值
  • 建网站语言wordpress联系浮动
  • 九江市住房和城乡建设局网站自助建站管理平台
  • 响应式网站用什么做做游戏交易网站有哪些
  • 国内html5视频网站建设wordpress 坐标
  • jsp网站建设项目实践网站域名密码找回
  • wordpress 兼职seo推广分析关键词的第一个步骤
  • 网站优化就是seo线上做笔记的网站
  • 实验中心网站建设的调查问卷南沙网站建设wwiw
  • 网站数据库连接错误开发公司设计部工作建议
  • 藁城区建设局网站网页版微信app
  • 中国建设银行网站特色访问wap网站
  • tp框架可以做网站吗长沙网站建
  • 做网络主播网站违法吗宝塔部署wordpress
  • 免费情感网站哪个好企业为什么做网站 图片
  • 浙江网站建设企业免费下载应用软件
  • 宁波网站建设方案联系方式艺术品电商网站开发
  • 重庆响应式网站建设网络舆情案例
  • 建设行业网站大概需要都少钱网站代码制作
  • 外贸做零售的网站网站建设运营必备人员
  • 西宁市城乡规划和建设局网站无锡模板网站
  • 企业网站制作公司盈利做问卷不花钱的网站