《一种用于嵌入式系统的内存控制方法.pdf》由会员分享,可在线阅读,更多相关《一种用于嵌入式系统的内存控制方法.pdf(13页完整版)》请在专利查询网上搜索。
1、(10)申请公布号 CN 102915276 A (43)申请公布日 2013.02.06 C N 1 0 2 9 1 5 2 7 6 A *CN102915276A* (21)申请号 201210360255.X (22)申请日 2012.09.25 G06F 12/02(2006.01) (71)申请人武汉邮电科学研究院 地址 430074 湖北省武汉市洪山区邮科院路 88号 (72)发明人陶琴 王凌斐 (74)专利代理机构武汉科皓知识产权代理事务 所(特殊普通合伙) 42222 代理人严彦 (54) 发明名称 一种用于嵌入式系统的内存控制方法 (57) 摘要 本发明提供一种用于嵌入式系统。
2、的内存控制 方法,从操作系统中申请一块内存,内存的一部分 作为内存池,另一部分作为预留内存区域;内存 池采用池式管理,结合线程缓存技术,为每个线程 建立一个缓存;预留内存区域采用TLSF算法管 理;将该内存池切割成不同大小的内存块,同等 大小的内存块连成双向链表,为每个内存块增加 一个内存管理单元,内存管理单元和内存块分别 放在不同的内存区域;为每一个线程建立一个内 存统计链表,用于连接所有此线程申请的内存块, 为方便内存泄露排查。另外,在不增加内存控制方 法开销的前提下,增加了内存覆盖检查机制。 (51)Int.Cl. 权利要求书2页 说明书8页 附图2页 (19)中华人民共和国国家知识产权。
3、局 (12)发明专利申请 权利要求书 2 页 说明书 8 页 附图 2 页 1/2页 2 1.一种用于嵌入式系统的内存控制方法,其特征在于:从操作系统中申请一块内存, 内存的一部分作为内存池,另一部分作为预留内存区域;内存池采用池式管理,为每个线程 配置一个线程缓存;预留内存区域采用TLSF算法管理; 进行内存初始化操作时,执行以下步骤, 步骤1.1,初始化内存池,包括将内存池切割成不同大小的内存块,为同等大小的内存 块维护一个内存管理头结构;为每个内存块分配一个内存管理单元; 步骤1.2,初始化预留内存区域,包括按照TLSF算法的数据结构组织预留内存区域,并 维护两个内存管理头结构,一个用来。
4、管理小内存块,另一个用来管理大内存块,小内存块和 大内存块根据预设参数划分; 步骤1.3,初始化各线程缓存的内存管理头结构,为任一线程申请的内存中同等大小的 内存块维护一个内存管理头结构; 步骤1.4,初始化每个线程的一个内存统计链表,所述内存统计链表是用于连接任一线 程申请的所有内存块; 内存池、预留内存区域和各线程缓存的内存管理头结构均包括空闲内存块的个数、已 使用内存块的个数、空闲链表、已使用链表和互斥锁;内存池和预留内存区域的各内存块的 内存管理单元的域包括内存池双向链表、线程缓存链表、内存块状态、线程使用内存统计链 表、内存管理参数和指向内存块的指针,内存管理参数包括内存块的大小si。
5、ze,所述内存池 双向链表为空闲链表或已使用链表;预留内存区域中,用来管理小内存块的内存管理头结 构中已使用链表称为小内存链表,预留内存区域中,用来管理大内存块的内存管理头结构 中已使用链表称为大内存链表; 进行内存分配操作时,执行以下步骤, 步骤2.1,根据应用程序申请的内存大小,向上调整到内存池中切割内存块的大小,记 为目标size;查看线程缓存对应大小内存块的空闲链表中是否是合适的内存块, 如果有,将内存块从线程缓存的空闲链表中删除,挂在线程缓存的已使用链表中,并更 新该内存块的内存管理单元的相关信息,包括状态更新为已使用,并标记为从内存池中分 配,返回内存块的首地址,将此内存块加入到线。
6、程的内存统计链表中,完成分配; 否则,进入步骤2.2; 步骤2.2,查看内存池中是否有目标size的空闲内存块, 如果有,将空闲的内存块从内存池的空闲链表中移除,挂在内存池的使用链表中,并更 新内存管理单元的相关信息,包括状态更新为已使用,并标记为从内存池中分配,返回内存 块首地址,将此内存块加入到线程的内存统计链表中,完成分配; 否则,进入步骤2.3; 步骤2.3,查找比目标size大一个size的内存块, 如果有,将空闲内存块从内存池的空闲链表中移除,挂在内存池的使用链表中,并更新 内存管理单元的相关信息,尤其是状态更新为已使用,并标记为从内存池中分配,返回内存 块首地址,将此内存块加入到。
7、线程的内存统计链表中,完成分配; 否则,根据应用程序申请的内存大小从预留内存区域中申请内存块,并分配相应的内 存管理单元;设置内存管理单元的相关信息,包括状态为已使用,并标记为从预留内存区域 中分配;返回内存块首地址,将此内存块加入到线程的内存统计链表中;根据应用程序申 权 利 要 求 书CN 102915276 A 2/2页 3 请的内存大小和预设参数,确定申请的内存块是小内存块还是大内存块;如果申请的是小 内存块,将申请的内存块挂到小内存链表中,并更新哈希表的信息,将此内存块插入到二级 哈希结构中,完成分配;如果申请的是大内存块,将申请的内存块挂到大内存链表中; 进行内存释放操作时,执行以。
8、下步骤, 步骤3.1,由输入地址找到对应的内存管理单元; 步骤3.2,根据内存管理单元中的内存块状态域来判断, 如果是从内存中的内存池申请的,转入步骤3.3; 如果是从预留内存区域分配的,将内存管理单元从预留内存区域的对应内存管理头结 构的已使用链表中删除,将内存块从线程的内存统计链表中删除,如果是小内存块则更新 哈希查找结构的信息;并采用TLSF算法的free函数释放内存块和相应内存管理单元,完成 释放; 步骤3.3,将内存管理单元从内存池的使用链表中移除,挂到线程缓存的空闲链表中, 并更新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完成释放; 步骤3.4,检查线程缓存中空闲内存。
9、块数目与使用内存块数目的比值, 如果小于一定阈值,则将内存管理单元从线程缓存的使用链表中移除,挂到线程缓存 的空闲链表中,并更新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完成 释放; 否则,将内存管理单元从线程缓存的使用链表中移除,挂到内存池的空闲链表中,并更 新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完成释放。 2.根据权利要求1所述用于嵌入式系统的内存控制方法,其特征在于:进行内存覆盖 检查时,对要定位的内存块执行以下步骤, 步骤4.1,根据输入地址判断该内存块是在内存池中还是预留内存区域中, 如果是在内存池中,则先定位该内存块位于哪个size内存块的范围,然。
10、后取模运行定 位内存边界; 如果是在预留内存区域中,则转入步骤4.2; 步骤4.2,遍历大内存链表查找该内存块, 如果查找到则得到内存边界, 否则,采用二级哈希算法来定位内存边界。 3.根据权利要求1或2所述用于嵌入式系统的内存控制方法,其特征在于:内存池中, 内存管理单元和内存块分别放在不同的内存区域;预留内存区域中,内存管理单元和内存 块分别放在不同的内存区域。 权 利 要 求 书CN 102915276 A 1/8页 4 一种用于嵌入式系统的内存控制方法 技术领域 0001 本发明涉及嵌入式系统技术领域,尤其是涉及嵌入式系统的内存控制方法。 背景技术 0002 嵌入式系统的内存资源相当有。
11、限,故需要对其进行合理的规划和管理。内存是系 统中所有线程运行的基础,是嵌入式系统最重要的系统资源。简单、高效的内存组织和管 理,是系统稳定、高速运行的保证。嵌入式系统对内存分配要求达到快速性、可靠性和高效 性。一种常见的管理方式就是内存池方式。 0003 其实现机制是一次性将后续所有应用程序需要使用的内存全部申请下来,切割成 各种固定大小的不同数量的内存块,按照一定的数据结构形成内存池,然后按需进行二次 分配。 0004 设计内存池的目的是为了保证服务器长时间高效的运行,通过对申请空间小而申 请频繁的对象进行有效管理,减少内存碎片的产生,合理分配管理用户内存,从而减少系统 中出现有效空间足够。
12、,而无法分配大块内存的情况。而且内存池实现简单,分配和回收较 快。 0005 但是内存池也是存在一定缺点的,所有的进程共享同一个内存池,多个进程的多 个任务都在分配释放内存块时会竞争同一个锁,锁的开销会大大降低内存管理方式的效 率。另外,内存池的控制信息和应用层的内存块连续存放,一旦发生应用程序内存覆盖的误 操作,往往会覆盖内存块的控制信息,有可能会导致包括系统崩溃在内的严重后果。 0006 此外,C代码中指针的应用会带来内存越界的隐患,经常出现某段内存的内容被修 改而导致系统运行异常,可出现异常时只是犯罪现场,无法定位出是谁修改了这段内存。对 这些情况,通常的做法,只能是审查代码,凭经验找出。
13、可能出错的代码,进行大量的分析试 验,才能找到真凶。 发明内容 0007 本发明提出了一种内存控制方法,其目的在于增加内存覆盖检查机制,提高内存 使用效率,减少应用程序内存覆盖的概率。 0008 本发明的技术方案为一种用于嵌入式系统的内存控制方法,从操作系统中申请一 块内存,内存的一部分作为内存池,另一部分作为预留内存区域;内存池采用池式管理,为 每个线程配置一个线程缓存;预留内存区域采用TLSF算法管理; 进行内存初始化操作时,执行以下步骤, 步骤1.1,初始化内存池,包括将内存池切割成不同大小的内存块,为同等大小的内存 块维护一个内存管理头结构;为每个内存块分配一个内存管理单元; 步骤1.。
14、2,初始化预留内存区域,包括按照TLSF算法的数据结构组织预留内存区域,并 维护两个内存管理头结构,一个用来管理小内存块,另一个用来管理大内存块,小内存块和 大内存块根据预设参数划分; 说 明 书CN 102915276 A 2/8页 5 步骤1.3,初始化各线程缓存的内存管理头结构,为任一线程申请的内存中同等大小的 内存块维护一个内存管理头结构; 步骤1.4,初始化每个线程的一个内存统计链表,所述内存统计链表是用于连接任一线 程申请的所有内存块; 内存池、预留内存区域和各线程缓存的内存管理头结构均包括空闲内存块的个数、已 使用内存块的个数、空闲链表、已使用链表和互斥锁;内存池和预留内存区域的。
15、各内存块的 内存管理单元的域包括内存池双向链表、线程缓存链表、内存块状态、线程使用内存统计链 表、内存管理参数和指向内存块的指针,内存管理参数包括内存块的大小size,所述内存池 双向链表为空闲链表或已使用链表;预留内存区域中,用来管理小内存块的内存管理头结 构中已使用链表称为小内存链表,预留内存区域中,用来管理大内存块的内存管理头结构 中已使用链表称为大内存链表; 进行内存分配操作时,执行以下步骤, 步骤2.1,根据应用程序申请的内存大小,向上调整到内存池中切割内存块的大小,记 为目标size;查看线程缓存对应大小内存块的空闲链表中是否是合适的内存块, 如果有,将内存块从线程缓存的空闲链表中。
16、删除,挂在线程缓存的已使用链表中,并更 新该内存块的内存管理单元的相关信息,包括状态更新为已使用,并标记为从内存池中分 配,返回内存块的首地址,将此内存块加入到线程的内存统计链表中,完成分配; 否则,进入步骤2.2; 步骤2.2,查看内存池中是否有目标size的空闲内存块, 如果有,将空闲的内存块从内存池的空闲链表中移除,挂在内存池的使用链表中,并更 新内存管理单元的相关信息,包括状态更新为已使用,并标记为从内存池中分配,返回内存 块首地址,将此内存块加入到线程的内存统计链表中,完成分配; 否则,进入步骤2.3; 步骤2.3,查找比目标size大一个size的内存块, 如果有,将空闲内存块从内。
17、存池的空闲链表中移除,挂在内存池的使用链表中,并更新 内存管理单元的相关信息,尤其是状态更新为已使用,并标记为从内存池中分配,返回内存 块首地址,将此内存块加入到线程的内存统计链表中,完成分配; 否则,根据应用程序申请的内存大小从预留内存区域中申请内存块,并分配相应的内 存管理单元;设置内存管理单元的相关信息,包括状态为已使用,并标记为从预留内存区域 中分配;返回内存块首地址,将此内存块加入到线程的内存统计链表中;根据应用程序申 请的内存大小和预设参数,确定申请的内存块是小内存块还是大内存块;如果申请的是小 内存块,将申请的内存块挂到小内存链表中,并更新哈希表的信息,将此内存块插入到二级 哈希。
18、结构中,完成分配;如果申请的是大内存块,将申请的内存块挂到大内存链表中; 进行内存释放操作时,执行以下步骤, 步骤3.1,由输入地址找到对应的内存管理单元; 步骤3.2,根据内存管理单元中的内存块状态域来判断, 如果是从内存中的内存池申请的,转入步骤3.3; 如果是从预留内存区域分配的,将内存管理单元从预留内存区域的对应内存管理头结 构的已使用链表中删除,将内存块从线程的内存统计链表中删除,如果是小内存块则更新 说 明 书CN 102915276 A 3/8页 6 哈希查找结构的信息;并采用TLSF算法的free函数释放内存块和相应内存管理单元,完成 释放; 步骤3.3,将内存管理单元从内存池。
19、的使用链表中移除,挂到线程缓存的空闲链表中, 并更新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完成释放; 步骤3.4,检查线程缓存中空闲内存块数目与使用内存块数目的比值, 如果小于一定阈值,则将内存管理单元从线程缓存的使用链表中移除,挂到线程缓存 的空闲链表中,并更新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完成 释放; 否则,将内存管理单元从线程缓存的使用链表中移除,挂到内存池的空闲链表中,并更 新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完成释放。 0009 而且,进行内存覆盖检查时,对要定位的内存块执行以下步骤, 步骤4.1,根据输入地址判断该内。
20、存块是在内存池中还是预留内存区域中, 如果是在内存池中,则先定位该内存块位于哪个size内存块的范围,然后取模运行定 位内存边界; 如果是在预留内存区域中,则转入步骤4.2; 步骤4.2,遍历大内存链表查找该内存块, 如果查找到则得到内存边界, 否则,采用二级哈希算法来定位内存边界。 0010 而且,内存池中,内存管理单元和内存块分别放在不同的内存区域;预留内存区域 中,内存管理单元和内存块分别放在不同的内存区域。 0011 本发明的创新点在于: 1.为每个内存块增加一个内存管理单元,在管理单元中增加了容错信息,记录所有与 内存分配、回收以及内存块状态的信息,实现内存使用状态监控、内存泄露探测。
21、等功能; 2.将数据段和管理单元的内存分离,以防止内存小范围越界,影响内存管理单元; 3.将内存池与线程缓存技术结合,并启动主动回收和强制回收机制,避免大量内存碎 片的同时,有效地提高了分配的效率,对多线程多进程的系统尤为适用; 4.增加了内存覆盖检查机制,设计了一套定位内存边界的算法,对于非连续的内存块, 以地址为哈希key,通过二级哈希结构来定位,从源头上杜绝内存覆盖; 5.由于在内存管理结构中增加了状态监控、内存泄露等探测功能,在内存申请释放时 加入了使用内存块的统计信息,对于程序中的内存泄露,可以较快的定位出来。 附图说明 0012 图1为本发明实施例中内存池的数据结构图; 图2为本发。
22、明实施例中内存统计的数据结构图; 图3为本发明实施例中内存池中内存块状态变化图; 图4为本发明实施例中哈希查找结构的地址key划分图; 图5为本发明实施例中哈希查找结构图。 0013 具体实施方式 以下结合附图和实施例详细说明本发明技术方案。 说 明 书CN 102915276 A 4/8页 7 0014 本发明的内存控制机制适用于共享内存,堆内存等,首先从操作系统中申请一大 块内存,一部分作为内存池,另一部分作为预留内存区域,基于内存池和预留内存区域的内 存管理操作具体包括内存初始化、内存分配、内存释放、缓存回收、内存覆盖检查。内存池采 用池式管理,结合线程缓存技术,为每个线程建立一个缓存,。
23、避免所有线程竞争同一个锁的 情况,并增加主动回收和强制回收机制,保证内存池对其他线程的供应,此机制避免了内存 碎片,并有效提高了进程间通信的效率;预留内存区域采用TLSF算法来管理,以避免内存 池中空闲内存块不足的情况,预留一段内存区域。TLSF算法具体实现为现有技术。 0015 实施例中,内存初始化操作包括: 步骤1.1,初始化内存池,内存池的数据结构如图1所示,将此内存切割成多组固定大 小的内存块,每组内存块字节大小是一致的,如图1中32字节的所有内存块为一组,64字节 的所有内存块为一组。实施例中每组内存块的大小为2的幂次方字节,比如第0组内存块 的大小均为32字节,第1组内存块的大小均。
24、为64字节,以此类推,第n组内存块的大小均 为2(n+5)。内存区域切割成固定大小的内存块后,同等大小的内存块连成双向链表,可采 用一个空闲链表和一个已使用链表。初始化的时候所有内存块都是挂在空闲链表中,已使 用的内存块改为挂在已使用链表中。 0016 实施例对于相同大小的内存块,维护一个管理头结构,记录空闲内存块的个数、已 使用内存块的个数、空闲链表和已使用链表。如图1中的32字节管理头结构、64字节管理 头结构、128字节管理头结构、256字节管理头结构等。其中,空闲链表连接所有空闲的内存 块,已使用链表连接所有已使用的内存块。管理头结构还包含一个互斥锁(mutex域),用于 在分配/释放。
25、时,对链表的访问实现多线程的互斥访问。 0017 另外,为每个内存块建立对应的内存管理单元,用来记录所有与内存分配、回收相 关的信息,实现内存使用状态监控、内存泄露探测等功能。实施例的内存管理单元中的参数 包括: 1)内存池双向链表:内存池中链接同等大小的内存块管理单元; 2)线程缓存链表:线程缓存中链接同等大小的内存块管理单元; 3)内存块状态:记录当前内存块的使用状态及所在的区域(内存池或TLSF预留区域); 根据内存块状态可知其是否被使用,即可进行重复释放检查; 4)内存块大小:记录当前内存块可使用的大小,例如图1中32字节管理头结构下的内 存管理单元内存块大小均为32字节; 5)线程使。
26、用内存统计链表:每个线程会维护图2的一个统计链表表头,统计各线程的 内存使用情况,此项参数是用来链接同一线程申请的内存管理单元,以便随时可以查看内 存使用情况,检查是否存在内存泄露; 6)内存管理参数:包括内存块申请释放的时间、申请内存的文件名和函数名,方便出 错时跟踪内存使用流程; 7)指向内存块的指针:内存块才是真正返回给应用程序使用的一段内存,在内存管理 单元中维护这个指针,主要是为了根据内存管理单元较方便找到对应的内存块。 0018 图1中的内存块是实际分配给应用程序使用的一段内存,理论上是按照上述32 字节、64字节切割即可,为了防止内存越界,在各字节内存块前后各预留一个红灯区(Re。
27、d zone1和Red zone2),保护内存块。另外,内存块中还维护一个指针,指向其内存管理单元, 说 明 书CN 102915276 A 5/8页 8 方便根据内存块迅速定位到对应的内存管理单元。 0019 内存管理单元和内存块分别放在内存不同的内存区域,以防止发生应用程序内存 覆盖的误操作,覆盖内存块的内存管理单元,有可能会导致包括系统崩溃在内的严重后果。 0020 步骤1.2,初始化预留内存区域,按照TLSF算法(Two Levels Segregate Fit memory allocator,二级隔离适应算法)的数据结构将预留内存区域组织起来,并初始化两 个内存管理头结构,一个用来。
28、管理小内存块,另一个用来管理大内存块。为方便描述起见, 用来管理小内存块的内存管理头结构中已使用链表称为小内存链表,预留内存区域中,用 来管理大内存块的内存管理头结构中已使用链表称为大内存链表。 0021 划分大小内存块的预设参数用户可根据实际需求来设置。区分大小内存块主要 是为了后续的内存覆盖检查,哈希查找算法只针对小内存块,假定小于等于8192字节的 内存块为小内存,大于8192字节的内存块为大内存,那么对于大内存块的地址,低13位 (213=8192)是完全一样的,如果采用哈希查找算法,哈希冲突太多,很难均匀的散列开来。 因此可以初始化用于内存覆盖检查的哈希查找头结构(如图5中一级哈希桶。
29、)。 0022 对于预留内存区域的管理,不是像内存池一样预先分割好,也没有缓存机制,而是 在申请时从预留内存区域中根据申请需要分配相应大小的内存块,并分配一个内存管理单 元。因此具体实施时,预留内存区域的内存管理头结构和内存管理单元具体结构与内存池 的可以一致,只是空闲链表无需使用。预留内存区域中,内存管理单元和内存块也分别放在 不同的内存区域。 0023 步骤1.3,初始化各线程缓存的内存管理头结构,这个结构同内存池各组内存块的 内存管理头结构一致,包括空闲内存块的个数、已使用内存块的个数、空闲链表和已使用链 表、互斥锁。线程可能申请不同大小的内存块,每个线程针对不同字节大小分别建立内存管 。
30、理头结构,也是同等大小的内存建立一个内存管理头结构,如32字节有一个管理头结构, 64字节同样有一个管理头结构,不同字节大小的管理头结构用数组来组织。 0024 各线程缓存的内存管理头结构和申请的内存块的内存管理单元具体结构与内存 池的也保持一致。 0025 步骤1.4,初始化各线程的内存统计链表(即线程使用内存统计链表)的表头,数 据结构如图2所示,内存统计链表头包括申请的内存块的总数目、申请的内存块的总大小、 互斥锁和双向链表。此处双向链表是用来连接所有此线程申请的内存块,具体是附图1中 的线程内存使用统计链表。 0026 实施例为每一个线程建立一个内存统计链表,用来连接所有此线程申请的内。
31、存 块,供内存泄露探测用。申请内存完毕会将内存块挂到此内存统计链表中,记录该线程申请 的所有内存块,以方便进行内存泄露排查。 0027 具体实施时,步骤1.1和步骤1.2可以不分先后,在进程启动开始时完成即可,步 骤1.1中内存池各内存块大小及其分布,可通过预设的配置文件来配置;步骤1.3、步骤1.4 可以不分先后,在线程启动开始时完成即可。 0028 内存分配/释放操作负责为上层应用程序提供内存分配/释放的接口,本发明改 进了传统的池式管理机制,将内存池算法与线程缓存技术结合,并预留一段内存采用TLSF 算法来管理,以避免内存池中空闲内存块不足的情况,避免了大量的内存碎片。同时,为每 一个线。
32、程配置一个缓存,线程分配释放优先从缓存池中查找,减少了所有线程竞争同一个 说 明 书CN 102915276 A 6/8页 9 锁的开销,大大提高了分配的效率。 0029 本发明分配内存块时,先检查线程缓存池中是否有对应固定大小的空闲内存块, 如果有则从线程缓存池中分配内存块,并更新内存块的状态为已使用;如果线程缓存池中 没有对应固定大小的空闲内存块,则从内存池的空闲链表中分配,并更新内存块的状态为 已使用。如果内存池中某个固定大小的内存块不能满足应用程序的需求,则分配大一个 size的内存块;如果内存池中大一个size的内存块也没有,则从预留的内存区域中采用 TLSF算法来分配内存。TLSF。
33、算法采用位图管理,两级索引,实现简单,动态性较强。 0030 实施例中内存分配步骤如下: 步骤2.1,根据应用程序申请的内存大小,向上调整到内存池中内存块的大小,即调整 为2的幂次方的大小的内存块,例如应用程序申请31字节的内存,则从32字节的内存块中 查找空闲块。查看线程缓存对应大小内存块的空闲链表中是否是合适的内存块, 如果有,将内存块从线程缓存的空闲链表中删除,挂在线程缓存的已使用链表中,并更 新该内存块的内存管理单元的相关信息,尤其是状态更新为已使用,并标记为从内存池中 分配,返回内存块的首地址,将此内存块加入到线程的内存统计链表中,完成分配;否则,进 入步骤2.2; 步骤2.2,查看。
34、内存池中是否有合适的空闲内存块, 如果有,将空闲的内存块从内存池的空闲链表中移除,挂在内存池的使用链表中,并更 新内存管理单元的相关信息,尤其是状态更新为已使用,并标记为从内存池中分配,返回内 存块首地址,将此内存块加入到线程的内存统计链表中,完成分配; 否则,进入步骤2.3; 步骤2.3,查找大一个size的内存块,即例如32字节的内存块已全部使用完,则检查内 存池中64字节是否有空闲的内存块, 如果有,将空闲内存块从内存池的空闲链表中移除,挂在内存池的使用链表中,并更新 内存管理单元的相关信息,尤其是状态更新为已使用,并标记为从内存池中分配,返回内存 块首地址,将此内存块加入到线程的内存统。
35、计链表中,完成分配; 否则,说明此时内存池中的对应size的内存块不够用,根据应用程序申请的内存大小 从预留内存区域中申请内存块,并分配相应的内存管理单元,;设置内存管理单元的相关信 息,包括状态为已使用,并标记为从预留内存区域中分配,返回内存块首地址,将此内存块 加入到线程的内存统计链表中。根据应用程序申请的内存大小,确定申请的是小内存块还 是大内存块。并将申请的内存块挂到内存管理头结构的已使用链表中。即如果申请的是大 内存块,将申请的内存块挂到大内存链表中;如果申请的是小内存块,将申请的内存块挂到 小内存链表中。如果申请的是小内存块,则需要更新哈希表的信息,将此内存块插入到二级 哈希结构中。
36、,完成分配。 0031 本发明释放内存块时,检查线程缓存池的空闲链表中是否缓存的内存块超过一定 阈值,如果是,则将内存块主动还给内存池;否则该内存块仍缓存在线程缓存池中。 0032 实施例内存释放的步骤如下: 步骤3.1,由输入地址(内存块地址)找到对应的内存管理单元; 具体实施时,可以提供内存分配/释放的库函数,供应用程序调用。内存释放的时候, 应用程序传入输入地址,以确定要释放哪块内存。 说 明 书CN 102915276 A 7/8页 10 0033 步骤3.2,根据内存管理单元中的内存块状态域来判断, 如果是从内存中的内存池申请的,转入步骤3.3; 如果是从预留内存区域分配的,将内存管。
37、理单元从预留内存区域的对应内存管理头结 构的已使用链表中删除,即若释放的内存块是大内存块则从大内存链表中删除,是小内存 块则从小内存链表中删除;将此内存块从线程的内存统计链表中删除,如果是小内存块还 需要更新哈希查找结构的信息;并采用TLSF算法的free函数释放内存块和相应内存管理 单元,完成释放; 步骤3.3,将内存管理单元从内存池的使用链表中移除,挂到线程缓存的空闲链表中, 并更新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完成释放; 步骤3.4,检查线程缓存中空闲内存块数目与使用内存块数目的比值, 如果小于一定阈值,则将内存管理单元从线程缓存的已使用链表中移除,挂到线程缓 。
38、存的空闲链表中,并更新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完 成释放; 否则,将内存管理单元从线程缓存的已使用链表中移除,挂到内存池的空闲链表中,并 更新状态域为空闲状态,将此内存块从线程的内存统计链表中删除,完成释放。用户可根据 实际使用来情况预先设定阈值,实施例中将其设置为1; 完成释放即可结束流程。 0034 本发明进一步提出,缓存回收过程的实现可同时采用主动回收机制和强制回收机 制,释放内存的时候,会检查线程缓存中空闲内存块数目与使用内存块数目的比值,如果超 过阈值(本实施例中为1)则启动主动回收机制,将内存归还给内存池。同时维护一个线程 专门负责强制回收,如果内存。
39、池中空闲内存块不足,则强制回收线程缓存中的空闲内存块。 0035 实施例中,专门维护一个线程负责强制回收,维护一个全局信号量和全局数组,全 局信号量用来唤醒强制回收线程,全局数组用来通知强制回收线程哪个size的内存块需 要强制回收。每次分配内存时检查内存池中空闲内存的数量,如果全局内存池中空闲内存 块的数量低于设计的阈值,则唤醒一个全局信号量,并将全局数组的对应元素置为1,启动 强制回收机制。强制回收线程一直等待该全局信号量,如果等到信号量,则检查全局数组各 个元素哪个被置1了,确认哪种size的内存块需要被强制回收。确认后依次遍历每个线程 缓存中该size的内存管理头结构,将线程缓存空闲链。
40、表中的内存管理单元全部移除到相 应的全局内存池的空闲链表中。回收完成之后,需要将全局数组的该元素清零。 0036 综上所述,内存池中内存块的状态变化请参见图3,内存池初始化完,所有的内存 块均挂在内存池的空闲链表下,状态为空闲;被分配出去之后,该内存块挂在线程缓存的已 使用链表下,状态为已使用;释放的时候,如果线程缓存的内存块未超过一定阈值,则将该 内存块移到线程缓存的空闲链表下,否则启动主动回收机制,将该内存块挂到内存池的空 闲链表下,状态为空闲;另外,如果内存池中空闲内存块低于一定阈值,启动强制回收机制, 会将内存块从线程缓存的空闲链表中移到内存池的空闲链表中,状态为空闲。 0037 本发。
41、明还包含了一种内存覆盖检查算法,内存覆盖检查的难点就是根据输入地址 定位出可使用的内存块的起始地址,即内存边界。内存覆盖检查操作通过定位内存块的起 始地址,来检查是否会出现内存覆盖。对于内存池,由于内存池中内存块地址是连续的,可 以通过取模运算来定位内存块的起始地址;对于预留内存区域,由于分配出去的内存地址 说 明 书CN 102915276 A 10 8/8页 11 不连续,采用两级哈希索引结构来定位内存边界,以内存地址作为哈希算法的key(关键码) 值。本方法无需改动内存管理方案,实用性较强。 0038 实施例的内存覆盖检查过程包括如下步骤: 步骤4.1,根据输入地址判断该内存块是在内存池。
42、中还是预留内存区域中, 如果是在内存池中,则先定位该内存块位于哪个size块的范围,然后取模运行即可定 位出内存块的边界; 如果是在预留内存区域中,则转入步骤4.2; 步骤4.2,遍历大内存链表查找该内存块, 如果查找到则得到内存边界, 否则,说明该内存块位于小内存块链表中,对这个链表中的内存块,采用二级哈希算法 来定位内存边界。 0039 本发明实施例以内存地址作为哈希关键码值,将内存地址分为3段,请参见图4: 高几位作为一级哈希的关键码值,中间的几位作为二级哈希的关键码值,对于一级哈希和 二级哈希关键码值具体取值,可依照实际工程中的情况而定,原则上是依据小内存块的大 小分布,尽量减少哈希冲。
43、突,使得不同的内存地址均匀的散列开来。本实施例中将小于 等于8192字节的内存块定义为小内存,针对小于8192字节的内存块做哈希运算。由于 8192=213,所以对于8192字节的内存块,其地址低13位是完全一样的,一级哈希取内存块 地址的高19位(19+13=32)作为其哈希关键码值,通过哈希运算将不同地址的内存块散列 开来。对于一级哈希冲突,采用再哈希法,取其地址的中间8位作为二级哈希关键码值。经 过两级哈希之后,内存地址由于剩下的低5位相同而产生冲突,采用链表的方式将其链接 起来,冲突链表的最大长度为25=32,不会影响查找效率。 0040 实施例的哈希结构图请参见图5,将一级哈希结构用。
44、哈希桶来存储,相同的哈希值 用同一个链表连起来,对链表中的每个节点,做二次哈希,同样采用哈希桶来存储,用链表 来链接哈希冲突值。当然,每次申请、释放内存块的时候都必须更新此套哈希结构,一级哈 希桶中的互斥锁是用来保证插入、删除和查找的同步。一级哈希桶包括一级哈希头节点、互 斥锁,一级哈希桶的桶深由一级哈希头节点的个数而定;一级哈希节点的参数包括哈希链 表、二级哈希头节点、一级哈希关键码值。二级哈希桶包括二级哈希头节点,二级哈希桶的 桶深由二级哈希头节点的个数而定;二级哈希节点的参数包括哈希链表、内存块起始地址、 内存块结尾地址。 0041 本文中所描述的具体实施例仅仅是对本发明精神作举例说明。本发明所属技术领 域的技术人员可以对所描述的具体实施例做各种各样的修改或补充或采用类似的方式替 代,但并不会偏离本发明的精神或者超越所附权利要求书所定义的范围。 说 明 书CN 102915276 A 11 1/2页 12 图1 图2 说 明 书 附 图CN 102915276 A 12 2/2页 13 图3 图4 图5 说 明 书 附 图CN 102915276 A 13 。