本发明涉及通信领域,具体而言,涉及一种存储空间管理方法及装置。
背景技术:
随着云计算和大数据技术的迅猛发展,用户对存储系统的存储效率与存储质量的要求越来越高,即,需要具备容量大、密度高、能耗低、读写速度快等特点的存储系统,而以动态随机存取存储器(Dynamic Random Access Memory,简称DRAM)与闪存Flash为代表的存储介质逐渐达到了技术瓶颈,例如容量和密度瓶颈。即,在相同面积下,DRAM与Flash的容量已经很难再增加;此外,在很多手持设备中,DRAM的能耗,特别是刷新能耗已经占据手持设备系统能耗的40%左右。而在一些数据中心中,DRAM的刷新能耗所带来的成本增加也是不容小觑的。对于Flash而言,虽然密度大于DRAM,但其读写速度远远慢于DRAM,且写入次数限制过小。这些不利因素,限制了Flash的未来应用。因此,长期以来研究人员都在不断地寻找满足要求的、新的存储介质。
随着新型非易失存储器(Non-Volatile Memory,简称NVM)取得了不小的进步,它们的大容量、高密度、低能耗、读写速度快、磨损周期长等特点引起了学术界和工业界的广泛关注,使人们在云计算、大数据时代背景下,看到了存储系统性能提升的希望,在云计算和大数据背景下,很多应用程序都会要求自己的数据或数据结构被持久化存储。而持久化内存不仅可以满足这一要求,还可以减少存储栈层次,提高存储效率。应用程序使用持久化内存最有效的一种方式,即将持久化内存映射到进程地址空间中。如此一来,应用程序就可以直接读写持久化内存区域,极大地减少额外开销。当有多个进程都需要映射持久化内存时,就要对整个持久化内存进行有效的组织和管理,并根据应用的需求将指定大小的持久化存储区域,映射到进程地址空间。映射完成后,该持久化存储区域便可称之为持久化堆,应用程序就可以在其中存储需要持久化的数据或数据结构。这就是持久化内存管理机制的应用场景和主要任务。但是由于NVM的持久性,即使重启系统,空闲空间也不会增多。若不对持久化空间的分配和释放操作进行优化处理,空闲空间很有可能在较短时间内耗尽。因此,空间性能对于持久化内存管理而言是非常重要的。
然而,上述的持久化内存管理方案,却在很大程度上忽视了空间效率。因此在如何解决NVM的内存管理问题上,目前尚未提出有效的解决方案。
技术实现要素:
本发明提供了一种存储空间管理方法及装置,以至少解决相关技术中缺少针对NVM的内存管理机制导致内存空间分配效率低下的问题。
根据本发明的一个方面,提供了一种存储空间管理方法,包括:接收应用程序的内存空间请求;获取内存空间请求中所请求的空闲页框数目;依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;将连续空闲存储空间分配给应用程序。
进一步地,在空闲页框组织包括:页框链表或树,页框链表或树包括:至少一个分配单元描述符,至少一个分配单元描述符用于描述连续存储空间的存储状态以及连续存储空间对应的页框的起始地址和长度的情况下,依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间的步骤包括:查询页框链表或树中的至少一个分配单元描述符;将至少一个分配单元描述符中对应的连续空闲存储空间的大小,与应用程序所请求的空闲页框数目对应的连续空闲存储空间进行匹配,查询是否存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;若存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间,则提取连续空闲存储空间作为分配至空闲页框数目对应的连续空闲存储空间;其中,连续存储空间的存储状态包括:已分配和空闲。
进一步地,将连续空闲存储空间分配给应用程序的步骤包括:若页框链表或树中的连续空闲存储空间的大小等于空闲页框数目对应的连续空闲存储空间大小,则将连续空闲存储空间分配给应用程序;若页框链表或树中的连续空闲存储空间的大小小于空闲页框数目对应的连续空闲存储空间大小,则在页框链表或树中查询N个连续空闲存储空间,判断N个连续空闲存储空间是否与空闲页框数目对应的连续空闲存储空间大小相等,N为整数,且大于1;在判断结果为是的情况下,将N个连续空闲存储空间分配给应用程序。
进一步地,方法还包括:若N个连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间,则在页框链表或树中查找大于空闲页框数目对应的连续空闲存储空间大小的第一连续空闲存储空间;若得到第一连续空闲存储空间,则对第一连续空闲存储空间进行切割,得到与空闲页框数目对应的连续空闲存储空间大小相等的第二连续空闲存储空间;将第二连续空闲存储空间分配给应用程序;其中,将第一连续空闲存储空间切割后的剩余连续空闲存储空间归还至页框链表或树;若页框链表或树中最大的连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间,则在空闲页框链表或树中查询是否存在小于最大连续空闲存储空间的连续存储空间,且连续存储空间的大小与空闲页框数目对应的连续空闲存储空间匹配,若连续存储空间小于空闲页框数目对应的连续空闲存储空间,则在空闲页框链表或树中查询是否存在小于连续空闲存储空间的连续存储空间,直至查询得到与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间,或,提示当前没有能够与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间。
进一步地,在将连续空闲存储空间分配给应用程序之后,方法还包括:接收应用程序的持久化内存请求,持久化内存请求用于指示查询应用程序预先存储的数据;依据持久化内存请求,通过内存系统中的对象描述符进行查询,得到应用程序预先存储的数据;其中,对象描述符用于指示包含至少一个分配单元描述符的页框链表或树。
根据本发明的另一方面,提供了一种存储空间管理装置,包括:第一接收模块,用于接收应用程序的内存空间请求;获取模块,用于获取内存空间请求中所请求的空闲页框数目;第一查询模块,用于依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;分配模块,用于将连续空闲存储空间分配给应用程序。
进一步地,在空闲页框组织包括:页框链表或树,页框链表或树包括:至少一个分配单元描述符,至少一个分配单元描述符用于描述连续存储空间的存储状态以及连续存储空间对应的页框的起始地址和长度的情况下,第一查询模块包括:查询单元,用于查询页框链表或树中的至少一个分配单元描述符;第一匹配单元,用于将至少一个分配单元描述符中对应的连续空闲存储空间的大小,与应用程序所请求的空闲页框数目对应的连续空闲存储空间进行匹配,查询是否存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;第二匹配单元,用于若存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间,则提取连续空闲存储空间作为分配至空闲页框数目对应的连续空闲存储空间;其中,连续存储空间的存储状态包括:已分配和空闲。
进一步地,分配模块包括:第一分配单元,用于在页框链表或树中的连续空闲存储空间的大小等于空闲页框数目对应的连续空闲存储空间大小的情况下,将连续空闲存储空间分配给应用程序;判断单元,用于在页框链表或树中的连续空闲存储空间的大小小于空闲页框数目对应的连续空闲存储空间大小的情况下,在页框链表或树中查询N个连续空闲存储空间,判断N个连续空闲存储空间是否与空闲页框数目对应的连续空闲存储空间大小相等,N为整数,且大于1;第二分配单元,用于在判断结果为是的情况下,将N个连续空闲存储空间分配给应用程序。
进一步地,分配模块还包括:空间查询单元,用于在N个连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间的情况下,在页框链表或树中查找大于空闲页框数目对应的连续空闲存储空间大小的第一连续空闲存储空间;空间切割单元,用于在得到第一连续空闲存储空间的情况下,对第一连续空闲存储空间进行切割,得到与空闲页框数目对应的连续空闲存储空间大小相等的第二连续空闲存储空间;第三分配单元,用于将第二连续空闲存储空间分配给应用程序;其中,将第一连续空闲存储空间切割后的剩余连续空闲存储空间归还至页框链表或树;第四分配单元,用于在页框链表或树中最大的连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间的情况下,在空闲页框链表或树中查询是否存在小于最大连续空闲存储空间的连续存储空间,且连续存储空间的大小与空闲页框数目对应的连续空闲存储空间匹配,若连续存储空间小于空闲页框数 目对应的连续空闲存储空间,则在空闲页框链表或树中查询是否存在小于连续空闲存储空间的连续存储空间,直至查询得到与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间,或,提示当前没有能够与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间。
进一步地,装置还包括:第二接收模块,用于在将连续空闲存储空间分配给应用程序之后,接收应用程序的持久化内存请求,持久化内存请求用于指示查询应用程序预先存储的数据;第二查询模块,用于依据持久化内存请求,通过内存系统中的对象描述符进行查询,得到应用程序预先存储的数据;其中,对象描述符用于指示包含至少一个分配单元描述符的页框链表或树。
通过本发明,采用接收应用程序的内存空间请求;获取内存空间请求中所请求的空闲页框数目;依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;将连续空闲存储空间分配给应用程序。解决了相关技术中缺少针对NVM的内存管理机制导致内存空间分配效率低下的问题,进而达到了提升NVM的内存管理效率的效果。
附图说明
此处所说明的附图用来提供对本发明的进一步理解,构成本申请的一部分,本发明的示意性实施例及其说明用于解释本发明,并不构成对本发明的不当限定。在附图中:
图1是根据本发明实施例的存储空间管理方法的流程图;
图2是根据本发明实施例的一种内存池结构的结构框图;
图3是根据本发明实施例的一种元数据内存池子池初始状态图;
图4是根据本发明实施例一种元数据内存池子池第一次分配后状态图;
图5是根据本发明实施例一种元数据内存池子池第二次分配后状态图;
图6是根据本发明实施例一种元数据内存池子池释放第一个元素后状态图;
图7是根据本发明实施例一种空闲页框组织结构图;
图8是根据本发明实施例的存储空间管理装置的结构框图;
图9是根据本发明实施例的一种存储空间管理装置的结构框图;
图10是根据本发明实施例的另一种存储空间管理装置的结构框图;以及,
图11是根据本发明实施例的又一种存储空间管理装置的结构框图。
具体实施方式
下文中将参考附图并结合实施例来详细说明本发明。需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。
需要说明的是,本发明的说明书和权利要求书及上述附图中的术语“第一”、“第二”等是用于区别类似的对象,而不必用于描述特定的顺序或先后次序。
实施例一
本实施例提供的存储空间管理方法可以适用于非易失存储存储器,其中,非易失存储存储器(Non-Volatile Memory,简称NVM)至少可以包括:阻变式存储器(Resistive RAM,简称RRAM)、相变存储器(Phase Change Memory,简称PCM)、磁性随机存储器(Magnetic RAM,简称MRAM)以及自旋力矩转移存储器(Spin-Torque Transfer RAM,简称STT RAM)。其中,该类型的存储器具备大容量、高密度、低能耗、读写速度快、磨损周期长等特点,该类型的存储器可以直接连接到处理器内存子系统中,即和内存总线相连。在这种情况下,NVM可被称为持久化内存,即持久化内存Persistent Memory。在云计算和大数据背景下,很多应用程序都会要求自己的数据或数据结构被持久化存储。而持久化内存不仅可以满足这一要求,还可以减少存储栈层次,提高存储效率。应用程序使用持久化内存最有效的一种方式,即将持久化内存映射到进程地址空间中。如此一来,应用程序就可以直接读写持久化内存区域,极大地减少额外开销。当有多个进程都需要映射持久化内存时,就要对整个持久化内存进行有效的组织和管理,并根据应用的需求将指定大小的持久化存储区域,映射到进程地址空间。映射完成后,该持久化存储区域便可称之为持久化堆,应用程序就可以在其中存储需要持久化的数据或数据结构。
但是由于相关持久化内存管理方案中基于传统页框管理机制在buddy系统基础之上,针对NVM磨损周期短、读写性能不对称等特性进行优化设计,而未考虑buddy系统带来的空间浪费问题。该问题主要表现在以下几个方面:
首先,在向buddy系统请求分配空间时,即使用户申请的页框数不是2的幂,但buddy系统总是按照2的幂进行分配。比如,用户只请求300个页框,但buddy系统会分配给它512个页框。显然,这浪费了212个页框。同样由于上述原因,可能会出现即使有足够的连续空间,也不能分配给用户的情况。比如,当前最大的连续空闲页框数是384,而用户同样申请300个页框。虽然空闲页框数大于请求的页框数,但buddy系统依然会尝试分配512个连续页框。显然,此时不能满足分配请求,而无形中这384个连续页框没有得到充分利用,导致了空间浪费。
其次,由于页表机制的存在,在向进程/内核地址空间映射时,被映射的存储空间不一定非要连续。而buddy系统没有充分利用这一点,只提供了连续页框的分配方式。 如此一来,就可能会出现即使有足够的不连续空闲空间,也不能满足用户分配要求的情况。在这种情况下,很有可能造成一些小的内存碎片长期得不到使用,导致空间浪费。
最后,虽然buddy系统只能按照2的幂进行页框分配,但是构建于buddy系统之上的内存管理机制,可以通过多次调用buddy系统,以达到满足非2的幂的空间请求的同时,保证不多分配空间给用户的目的。该方法是基于如下规律,即任何一个整数都能以二进制形式表示。比如用户申请255个页框,可以转换成8次对buddy系统的调用。其中,每次分别申请128、64、32、16、8、4、2、1个连续页框。该方法虽然避免了因buddy系统只按照2的幂进行分配所造成的空间浪费,但是引入了过多的元数据。每次buddy系统进行分配后,都需要一个元数据描述当前获得的空间。显然,上述例子中需要8个元数据,才能描述8次调用所获得的空间。因此,上述方法的主要缺陷,即元数据空间开销过大。
并且,在文件系统进行管理时,在NVM上建立文件系统,然后使用一个文件或其他对象映射进内存mmap的方式映射持久化内存。实际上,文件系统的应用场景和前面描述的持久化内存的应用场景是截然不同的。虽然可以使用文件系统完成持久化内存映射和反映射的任务,但是文件系统中的许多设计,对持久化内存应用场景而言是不合适的。使用文件系统管理持久化内存的主要问题,即元数据部分的空间开销过大。例如,在一些文件系统中,使用位图管理数据块,其中位图的长度和存储空间的大小成比例。如此一来,存储空间越大,位图所代表的元数据部分所占据的空间也就越大。换句话说,元数据的使用量不具备可扩展性,其空间开销过大。再比如,一些文件系统认识到了上述位图设计方案空间性能不佳,而采用了B树组织一个文件的若干连续存储空间。其中,B树节点的大小即一个数据块的大小,比如4KBytes。这种设计对于文件系统而言可能是高效的,但是对于持久化内存应用场景却是不适合的。应用程序在向持久化内存管理机制申请映射空间时,通常都会给出被映射的空间大小。因此,若要使用文件系统管理持久化内存,最高效的做法之一,就是在进行mmap操作之前,首先调用fallocate等函数为被映射的文件,尽可能地预留连续物理空间。虽然应用程序可以通过增大被映射文件的方式,以扩容其持久化堆空间,但是该操作往往只会发生在其持久化堆的剩余空间过小时。换句话说,一个持久化堆对应的映射文件,所包含的连续空间的个数,相对于普通文件而言很有限。因此在这种情况下,使用B树,甚至是使用B树的一个节点,组织被映射文件的、个数极其有限的连续空间,是非常浪费的。另外,文件系统中的一些元数据结构,比如块组及其描述符表等,对于持久化内存应用场景而言,完全是不需要的。显然,这部分元数据所占用的空间,也是被浪费掉了。
因此,本发明实施例针对上述问题提供一种存储空间管理方法,基于NVM介质特点和持久化内存应用场景,具体如下:
在本实施例中提供了一种存储空间管理方法,图1是根据本发明实施例的存储空间 管理方法的流程图,如图1所示,该流程包括如下步骤:
步骤S102,接收应用程序的内存空间请求;
步骤S104,获取内存空间请求中所请求的空闲页框数目;
步骤S106,依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;
步骤S108,将连续空闲存储空间分配给应用程序。
具体的,首先接收来自应用程序的内存空间请求,其次,在对该内存空间请求进行解析的过程中,获取该内存空间请求中该应用程序所请求的空闲页框数目,第三,在获取到空闲页框数目后查询页框链表或树,进而获取与该空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间,最后,将连续空闲存储空间分配给应用程序。
通过上述步骤,采用接收应用程序的内存空间请求;获取内存空间请求中所请求的空闲页框数目;依据空闲页框数目查询页框链表或树,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;将连续空闲存储空间分配给应用程序。解决了相关技术中缺少针对NVM的内存管理机制导致内存空间分配效率低下的问题,进而达到了提升NVM的内存管理效率的效果。
本实施例在实现存储空间管理方法的过程中还提供了以下两种元数据:
一是代表连续页框的分配单元描述符,其中,无论是空闲空间,还是已分配空间,均是分配单元描述符表示;且,分配单元描述符中,会存放其描述的连续页框的起始地址和长度等信息。
二是代表持久化堆的对象描述符。对应的,对象描述符会指向一个包含了若干分配单元描述符的链表,以表示其对应的持久化堆所包含的若干连续页框。为了减少元数据分配和释放操作所产生的内存碎片,本实施例还设计了元数据内存池。由于有两种元数据,所以分别实例化了分配单元描述符内存池和对象描述符内存池。
进一步地,在空闲页框组织包括:页框链表或树,页框链表或树包括:至少一个分配单元描述符,至少一个分配单元描述符用于描述连续存储空间的存储状态以及连续存储空间对应的页框的起始地址和长度的情况下,步骤S106中的依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间的步骤包括:
Step1,查询页框链表或树中的至少一个分配单元描述符;
Step2,将至少一个分配单元描述符中对应的连续空闲存储空间的大小,与应用程序所请求的空闲页框数目对应的连续空闲存储空间进行匹配,查询是否存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;
Step3,若存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间,则提取连续空闲存储空间作为分配至空闲页框数目对应的连续空闲存储空间。
其中,连续存储空间的存储状态包括:已分配和空闲。
具体的,在空闲页框组织(即,对应的连续空闲存储空间)方面,本实施例根据连续页框对应的连续空闲存储空间的大小,将连续空闲存储空间对应的分配单元描述符放入页框链表或树中。本实施例以提供了一共使用了127个空闲页框链表为例进行说明,其中,每个页框链表由多个分配单元描述符组成,同一个页框链表中分配单元描述符对应的存储空间大小相同。例如,第1个页框链表中,每个分配单元描述符对应的空间大小是1个页框;第2个页框链表中,每个分配单元描述符对应的空间大小是2个连续页框;第3个页框链表中,每个分配单元描述符对应的空间大小是3个连续页框,直至第127个页框链表中,每个分配单元描述符对应的空间大小时127个连续页框。
另外,本实施例还提供了以使用了5棵平衡二叉树为例进行说明,其中,该5可平衡二叉树用于存放较大的连续页框。其中,树的key即连续页框的大小。每棵树也是由多个分配单元描述符组成,同一棵树内的分配单元描述符对应的空间大小设置为在固定的范围内。例如,第1棵树中,每个分配单元描述符对应的空间大小在128个页框到255个页框之间,第2棵树中是在256个页框到511个页框之间,第3棵树中是在512个页框到1023个页框之间,第4棵树中是在1024个页框到2047个页框之间,超过2048个连续页框空闲空间对应的分配单元描述符,位于第5棵树。有可能存在多个分配单元描述符对应同一个树节点,即这些分配单元描述符所对应的连续空间大小相等。此时,会以链表的形式组织这些分配单元描述符,并由树节点指向该链表。
综上,通过查询页框链表或树中的至少一个分配单元描述符,将至少一个分配单元描述符中对应的连续空闲存储空间的大小,与应用程序所请求的空闲页框数目对应的连续空闲存储空间进行匹配,在页框链表或树中是否存在与应用程序请求的空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间。
进一步地,步骤S108中的将连续空闲存储空间分配给应用程序的步骤包括:
Step1,若页框链表或树中的连续空闲存储空间的大小等于空闲页框数目对应的连续空闲存储空间大小,则将连续空闲存储空间分配给应用程序;
具体的,根据应用程序请求的空闲页框数目对应的连续空闲存储空间的大小,在页框链表或树中查找和该空闲页框数目对应的连续空闲存储空间大小相等的连续空间。
或者,
Step2,若页框链表或树中的连续空闲存储空间的大小小于空闲页框数目对应的连续空闲存储空间大小,则在页框链表或树中查询N个连续空闲存储空间,判断N个连续空闲存储空间是否与空闲页框数目对应的连续空闲存储空间大小相等,N为整数,且大 于1;
Step3,在判断结果为是的情况下,将N个连续空闲存储空间分配给应用程序。
具体的,若在Step1的基础上,应用程序所请求的空闲页框数目对应的连续空闲存储空间的大小无法被满足,则依据Step2和Step3在页框链表或树中查找两个连续空闲存储空间的大小与该空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间。
本实施例以2个连续空闲存储空间为例对存储空间管理方法进行说明,以实现本实施例提供的存储空间管理方法为准,具体不做限定。
进一步地,在上述步骤S108中Step1至Step3并列的方案中,本实施了提供的存储空间管理方法还包括:
Step4,若N个连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间,则在页框链表或树中查找大于空闲页框数目对应的连续空闲存储空间大小的第一连续空闲存储空间;
Step5,若得到第一连续空闲存储空间,则对第一连续空闲存储空间进行切割,得到与空闲页框数目对应的连续空闲存储空间大小相等的第二连续空闲存储空间;
Step6,将第二连续空闲存储空间分配给应用程序;
其中,将第一连续空闲存储空间切割后的剩余连续空闲存储空间归还至页框链表或树;
具体的,基于Step1,Step2和Step3对应的连续空闲存储空间的分配方式,当Step1,Step2和Step3提供的分配方案均无法满足应用程序所请求的空闲页框数目对应的连续空闲存储空间的大小时,依据Step4至Step6提供的方法在页框链表或树中查找最接近、但大于所请求大小的第一连续空闲存储空间,在找到该第一连续空闲存储空间后,会对该第一连续空闲存储空间进行切割,分离出与空闲页框数目对应的连续空闲存储空间大小相等的第二连续空闲存储空间,并将剩下的连续空闲存储空间放入对应的页框链表或树中。
Step7,若页框链表或树中最大的连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间,则在空闲页框链表或树中查询是否存在小于最大连续空闲存储空间的连续存储空间,且连续存储空间的大小与空闲页框数目对应的连续空闲存储空间匹配,若连续存储空间小于空闲页框数目对应的连续空闲存储空间,则在空闲页框链表或树中查询是否存在小于连续空闲存储空间的连续存储空间,直至查询得到与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间,或,提示当前没有能够与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间。
具体的,当Step1,Step2和Step3以及Step4至Step6提供的分配方案均无法满足应用程序所请求的空闲页框数目对应的连续空闲存储空间的大小时,即当前系统最大连续空间都小于所请求的大小时,首先在空闲页框链表或树中查找最大的连续空间;其次,会递归地查找次大的连续空间,直到获取到满足该空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间为止。
此外,在进行页框释放时,会检查与被释放页框物理连续的页框的状态。若该物理连续的页框是空闲的,则会引发合并操作。即,只使用一个分配单元描述符表示合并后的连续页框。
由此得出,在页框分配以及释放的过程(即,连续空闲存储空间分配及释放的过程)中,本实施例提供的存储空间管理方法能够以使用最少的分配单元描述符为代价,满足应用程序对连续空闲存储空间的大小需求,以及在已分配的连续存储空间释放后,依然能够以一个分配单元描述符将已释放后的连续存储空间进行合并,从而节约系统资源。
进一步地,在步骤S108将连续空闲存储空间分配给应用程序之后,本实施例提供的存储空间管理方法还包括:
步骤S109,接收应用程序的持久化内存请求,持久化内存请求用于指示查询应用程序预先存储的数据;
步骤S110,依据持久化内存请求,通过内存系统中的对象描述符进行查询,得到应用程序预先存储的数据;
其中,对象描述符用于指示包含至少一个分配单元描述符的页框链表或树。
具体的,这里所说的对象,即持久化堆。由步骤S109和步骤S110中的方法,对象或持久化堆,是由对象描述符表示,该对象描述符中除了包含由分配单元描述符组成的页框链表外,还保存了持久化堆的标识。通过该标识,可以让应用程序找回之前申请到的持久化内存。本实施例中,将所有的对象描述符组织到一个平衡二叉树中。其中,树的key即持久化堆的标识。
本实施例提供的存储空间管理方法与相关技术的区别是:与基于传统页框管理机制的方案不同,本实施例不会多分配持久化内存给应用程序。而是依据Step1至Step7中对应描述的四种分配策略,无论哪一种策略,都是按照应用申请的页框数进行分配。即应用申请多少页框,就分配多少页框,不会出现浪费空间的情况。
其次,与基于传统页框管理机制的方案不同,本实施例不会出现有足够空闲空间,却不能进行分配的情况。仍旧依据Step1至Step7中对应描述的四种分配策略为例,在本实施例中当释放页框时,总是会尽力合并相邻的空闲连续页框。换句话说,在空闲链表和树中的连续页框都是不可再合并的。因此按照切割分配的原则,是不可能出现有足够的连续空间,却不能进行分配的情况。另一方面,组合分配和尽力分配的策略,会将 离散的多个连续空间组合起来进行分配。因此,也不可能出现有足够的若干不连续空间,却不能进行分配的情况。很显然,上述两项优势,有利于提升持久化内存的空间利用率。
第三,与相关的持久化内存管理方案相比,本实施例的元数据空间开销很小,且元数据使用量具有可扩展性。具体的,本实施例中,元数据主要包括分配单元描述符和对象描述符,而这两个描述符会构成链表或树的节点。其中,分配单元描述符包含了所描述的连续页框的起始地址和长度、与所描述的连续空间物理相邻的空间所对应的分配单元描述符的地址、构成链表或树的指针等信息;而对象描述符则包含了持久化堆标识、指向分配单元描述符链表的指针、构成树的指针等信息。很显然,本实施例设计的两种元数据所占的空间都很小,均在几十个字节以内。而与文件系统不同的是,将整个数据块作为一个B树节点。
在进行空闲页框分配时,每次只会增加一个或两个元数据。如果是新映射一个持久化堆,则会新增一个对象描述符;而如果只是对已有的持久化堆扩容,则不会增加对象描述符。下面说明分配单元描述符的增加情况。其中,在按照确切分配策略进行空间分配时,可以直接将找到的分配单元描述符,加入到对象描述符所包含的页框链表中。因此,不会增加新的分配单元描述符。在按照组合分配策略进行空间分配时,由于只会使用找到的两个分配单元描述符,因此该种情况也不会新增分配单元描述符。在按照切割分配策略进行空间分配时,会对找到的空闲空间进行分割,此时就需要一个新的分配单元描述符以表示切割后剩余的空间或分配出去的空间。在按照尽力分配策略进行空间分配时,会找到若干个分配单元描述符及其对应的空闲空间。如果这些空闲空间的大小之和,恰好等于请求的空间大小,则无需新增分配单元描述符。否则,将需要对最后找到的那个空闲空间进行切割。在这种情况下,将会新增一个分配单元描述符。进行持久化堆扩容时,本实施例在实施四项分配策略时,会尽量在原有空间的尾部(即高地址部分)分配新空间,即新空间和原有空间物理相邻。如此一来,就可以将原有空间和新空间进行合并,即减少分配单元描述符的个数。
在归还页框时,本实施例会合并物理相邻的空闲空间。因此,归还操作也可能会减少分配单元描述符。
本实施例中,除了对象描述符和分配单元描述符外,元数据部分还包括:大小固定的NVM总描述符和日志区域。其中,NVM总描述符和日志区域所占空间很小,只有一个页框。
综上,元数据部分的空间复杂度即为O(CN+ε),其中N为持久化堆的个数、C为一个堆进行扩容操作的次数、ε为NVM总描述符等代表的固定开销,而CN即持久化空间申请的次数。如前所述,通常情况下只有当持久化堆的剩余空闲空间不够用时,才会引发扩容操作,因此扩容次数即C通常很小,完全可以当作一个常量。如此一来,元数据部分的空间复杂度,只和持久化堆的个数有关,而与分配的空间大小或整个持久化内存大小无关,具备良好的可扩展性。
第四,本实施例在持久化内存内部为持久化堆建立了索引结构,即对象描述符组成的一棵平衡二叉树。通过持久化堆的标识,就可以在这棵树中找到对应的对象描述符,以及持久化堆所拥有的若干连续存储空间,即实现了页框找回。上述方案所提供的名字服务,仅依赖于持久化内存内部维护的数据结构,避免了之前分析的通过外部存储找回页框而带来的不可靠问题。
具体的,下面首先介绍本实施例中应用到的持久化内存的总体布局,然后再分析元数据及其内存池,并在此基础之上,介绍页框的组织与分配,以及对象描述符的组织与管理。
第一,内存布局:
在整个持久化内存空间的头部,有一个被称为NVM总描述符的固定大小区域。该区域包含了整个持久化内存管理机制的控制描述信息,比如各类标志信息、空闲页框管理结构信息等等。下面给出了这个头部区域的结构定义,即NVM总描述符。
struct NvmDescriptor
{
unsigned long FormatFlag;
unsigned long InitialFlag;
unsigned long NVMSize;
unsigned long MetaDataSize;
unsigned long FreePageNumber;
NvmAllocUnitDescriptorInList*FreePageLists[127];
NvmAllocUnitDescriptorInTree*FreePageTrees[5];
NvmObjectDestriptor*NvmObjectTree;
struct NvmMetaDataPool AllocUnitDescriptorMemoryPoolForList;
struct NvmMetaDataPool AllocUnitDescriptorMemoryPoolForTree;
struct NvmMetaDataPool NvmObjectDescriptorMemoryPool;
};
NvmDescriptor结构体中的各个字段解释如下:
FormatFlag:格式化标志,用于判断当前持久化内存是否已经完成了格式化。
InitialFlag:初始化标志,用于标识系统启动时故障恢复中的各个阶段。
NVMSize:NVM区大小,用于表示整个持久化内存的空间大小。
MetaDataSize:整个持久化内存中,元数据部分所占大小。
FreePageNumber:整个持久化内存中,未被使用的页框数目。
FreePageLists:空闲页框链表入口。该入口一共包含了127个指针,分别指向对应的空闲页框链表NvmAllocUnitDescriptorInList(该结构将在后面描述)。
FreePageTrees:空闲页框树入口。该入口一共包含了5个指针,分别指向对应的空闲页框树NvmAllocUnitDescriptorInTree(该结构将在后面描述)。
NvmObjectTree:对象描述符树入口,即指向对象描述符树NvmObjectDestriptor(该结构将在后面描述)。
AllocUnitDescriptorMemoryPoolForList:位于链表中的分配单元描述符内存池入口点结构。该入口点类型NvmMetaDataPool,将在后面描述。
AllocUnitDescriptorMemoryPoolForTree:位于树中的分配单元描述符内存池入口点结构。该入口点类型NvmMetaDataPool,将在后面描述。
NvmObjectDescriptorMemoryPool:对象描述符内存池入口点结构。该入口点类型NvmMetaDataPool,将在后面描述。
实际上,上述NvmDescriptor结构体占据在持久化内存的头部区域,即第一个页框中。其中,页框的大小设为4KBytes。由于NvmDescriptor的大小仅1KBbytes多,因此第一个页框的剩余部分作为了日志区域使用。
第二,元数据及内存池
a、元数据结构
如前所述,本专利方案使用了两种元数据,一是分配单元描述符,二是对象描述符。分配单元描述符用于表示一段连续页框,下面给出了其各个字段的定义。
struct NvmAllocUnitDescriptor
{
unsigned long SpaceAddress;
unsigned long SpaceSize;
unsigned long PreSpaceAddress;
unsigned long NextSpaceAddress;
unsigned long Flags;
};
NvmAllocUnitDescriptor即分配单元描述符,其各个字段含义如下。
SpaceAddress:当前分配单元描述符所表示的连续页框的基地址。
SpaceSize:当前分配单元描述符所表示的连续页框的大小。
PreSpaceAddress:与当前分配单元描述符所描述空间物理相邻(前驱)的连续空间, 对应的分配单元描述符的地址。
NextSpaceAddress:与当前分配单元描述符所描述空间物理相邻(后继)的连续空间,对应的分配单元描述符的地址。
Flags:当前分配单元描述符对应的连续空间的状态标志,包括是否是空闲空间等信息。
由于分配单元描述符可以位于链表或树中,因此NvmAllocUnitDescriptor结构体衍生出了两种包裹结构,即NvmAllocUnitDescriptorInList和NvmAllocUnitDescriptorInTree。这两个结构体的定义如下。
struct NvmAllocUnitDescriptorInList
{
struct NvmAllocUnitDescriptorInList*Prev;
struct NvmAllocUnitDescriptorInList*Next;
struct NvmAllocUnitDescriptor AllocDescriptor;
};
struct NvmAllocUnitDescriptorInTree
{
struct NvmAllocUnitDescriptorInTree*LeftChild;
struct NvmAllocUnitDescriptorInTree*RightChild;
struct NvmAllocUnitDescriptorInTree*Parent;
struct NvmAllocUnitDescriptorInList*SameSizeList;
struct NvmAllocUnitDescriptor AllocDescriptor;
};
从上述定义可以看出,NvmAllocUnitDescriptorInList结构代表了位于链表中的分配单元描述符,而NvmAllocUnitDescriptorInTree结构则代表了位于树中的分配单元描述符。其中,Prev和Next字段分别指向双向链表节点的前驱和后继节点,而LeftChild、RightChild和Parent字段,则分别指向了树中节点的左右孩子和父节点。另外,SameSizeList字段比较特殊。当分配单元描述符位于树中时,可能存在这样一种情况,即多个分配单元描述符所对应的连续空间大小相等。此时,本专利方案就将这些分配单元描述符,以链表形式组织,并由树节点指向。而SameSizeList字段,即为了构成上述链表。
对象描述符代表了持久化堆,其结构如下所示。
struct NvmObjectDestriptor
{
struct NvmObjectDestriptor*LeftChild;
struct NvmObjectDestriptor*RightChild;
struct NvmObjectDestriptor*Parent;
struct NvmAllocUnitDescriptorInList*SpaceList;
unsigned long NvmObjectSize;
unsigned long Flags;
unsigned char NvmUUID[16];
};
NvmObjectDestriptor中各个字段含义如下:
LeftChild、RightChild和Parent:由于持久化堆对应的对象描述符会位于一棵树中,因此上述三个字段分别指向了树中的左右孩子、父节点。
SpaceList:指向分配单元描述符链表,即一个由分配单元描述符组成的链表。该链表的每个元素,表示了持久化堆所拥有的连续空间。
NvmObjectSize:当前对象描述符表示的持久化堆空间的总大小。
Flags:当前持久化堆的各种标志。
NvmUUID:128位的持久化堆标识
b、元数据内存池
为了减少内存碎片,本专利方案为元数据建立了三种内存池,即位于链表中的分配单元描述符内存池、位于树中的分配单元描述符内存池和对象描述符内存池。这三种内存池的结构完全一致,不同点仅在于其内部管理的元数据大小不一。下面给出了内存池入口点的结构定义。
struct NvmMetaDataPool
{
unsigned long TotalElementNumber;
unsigned long FreeElementNumber;
struct NvmAllocUnitDescriptorInList*MetaDataFreeList;
struct NvmAllocUnitDescriptorInList*MetaDataFullList;
};
NvmMetaDataPool中的各个字段定义如下:
TotalElementNumber:内存池中总共元数据的个数。
FreeElementNumber:内存池中可分配的元数据个数。
MetaDataFreeList:指向可分配元素子池链表,链表中的每个元素是分配单元描述符。
MetaDataFullList:指向不可分配元素子池链表,链表中的每个元素是分配单元描述符。
一个内存池是由若干个内存子池构成的,而每个内存子池是由分配单元描述符表示。NvmMetaDataPool中包含的两个指针,分别指向了可分配元素子池链表和不可分配元素子池链表。前者还包含有空闲元数据,而后者的所有元数据均已被分配出去。图2给出了上述内存池的基本结构。
图2除了给出上述信息外,也给出了子池的基本结构。如前所述,内存池子池是由分配单元描述符表示,即通过该分配单元描述符可找到内存子池的实际存储空间。在这实际存储空间的头部,是一个NvmMetaDataSubPool结构体实例,用于控制内存子池中的分配和释放操作。下面给出了该结构体的定义。
struct NvmMetaDataSubPool
{
unsigned long TotalElementNumber;
unsigned long FreeElementNumber;
unsigned long FirstFreeElementAddress;
unsigned long FreedElementNumber;
};
NvmMetaDataSubPool中各个字段的含义如下:
TotalElementNumber:表示当前内存子池中总共的元素个数。
FreeElementNumber:表示当前内存子池中可供分配的元素个数。
FirstFreeElementAddress:表示当前内存子池中可供分配的第一个元素的地址。
FreedElementNumber:表示当前内存子池中被释放的元素个数,即以链表形式组织起来的元数据个数。该字段的具体含义见后面的分析。
内存子池实际存储区域中,除了头部的NvmMetaDataSubPool结构外,剩余部分都是用于元素存储。在内存池子池的内部存在一个链表,该链表是用于链接被释放的元素。每一个这样的元素的头8个字节,用于描述该元素相关的控制信息。元素的状态不同,其头8个字节的含义不同。元素存在三种状态:从未分配、已分配、被释放(其中从未分配和被释放都是空闲状态)。头8个字节的含义如下:
当元素为从未分配状态时,该元素后面可能存在若干连续元素,其状态都是从未分配。这种情况下,当前元素的头8个字节存储这种连续元素的个数。
当元素为已分配状态时,该元素的头8个字节存储其所在内存池子池对应的分配单元描述符结构的地址,即NvmAllocUnitDescriptorInList的地址。
当元素为被释放状态时,该元素的头8个字节存储下一个可分配元素的地址。
c、元数据的分配和释放
元数据的分配和释放建立在上述元数据内存池结构之上,下面说明具体的分配和释放步骤。
当接收到元数据分配请求后,首先判断所请求的元数据类型,即位于链表中的分配单元描述符、位于树中的分配单元描述符或对象描述符。
根据元数据类型,在NvmDescriptor结构和NvmMetaDataPool结构中获取可分配的内存子池的信息。
然后,在内存子池中完成元数据的分配操作。
对于释放操作而言,元数据的释放过程如下:
首先,当接收到元数据释放请求时,根据存储在元数据头8个字节内的信息,找到该元数据所属的内存子池对应的分配单元描述符,即NvmAllocUnitDescriptorInList结构体实例的地址。
其次,在找到的内存池子池中执行元数据释放操作。
从上面的讨论可知,元数据的分配和释放操作,主要发生在内存池子池内。下面将列举一个例子,说明如何在子池中进行元素的分配和释放。
初始化时,内存池子池的所有元素都是未分配的,图3给出了初始时的状态。在图3中,NvmMetaDataSubPool的FirstFreeElementAddress字段指向了该子池的第一个元素,也是第一个可以分配出去的元素。
当进行了第一次元素分配后,第一个可分配元素被分配出去了,即如图4所示。此时在图4中,FirstFreeElementAddress字段,指向了第二个元素。当再一次分配元素后,FirstFreeElementAddress字段将指向第三个元素,即如图5所示。假设第一个元素被释放,FirstFreeElementAddress字段将会指向被释放的元素,并在该元素中存储FirstFreeElementAddress字段之前指向的元素的地址。整个过程的最终结果,将会如图6所示。这样一来,被释放的元素将会组织进一个链表中,方便再次分配使用。
综上,本实施例中提到的元素可以为分配单元描述符对应的空闲的内存空间,以实现本实施例提供的存储空间管理方法为准,具体不做限定。
第三,空闲页框的组织、分配和释放
如前所述,本实施例将连续的空闲页框,按照其大小组织到了127个链表和5棵平衡二叉树中,即NvmDescriptor结构中的FreePageLists和FreePageTrees字段。图7给出了空闲页框的组织示意,该图的左侧是空闲页框链表入口点和空闲页框树入口点结构,而右侧则是若干连续空闲页框对应的分配单元描述符,组成的若干链表和平衡二叉树。在图7中,链表的元素和树的节点,均是分配单元描述符。另外,从图7中也可以看出,本专利方案采用的树是红黑树。
由于前面已经讨论了页框分配和释放的策略,这里仅就分配和释放的流程进行说明。主要的分配过程如下:
Step1,当接收到分配请求后,首先访问位于持久化内存头部的NvmDescriptor结构体。并根据其FreePageNumber字段,判断是否拥有足够的空闲页框。若空闲页框数不够,则出错返回。
Step2,若有足够的空闲页框,则判断请求的页框数量n,是否大于127个页框。若大于,则转向7)执行;否则,执行3)。
Step3,判断NvmDescriptor结构中的FreePageLists[n-1]链表,是否为空。若不是,则从该链表中取出一个分配单元描述符并将其返回给请求者,同时更新NvmDescriptor结构中的FreePageNumber字段。即,执行了确切分配的策略。
Step4,若FreePageLists[n-1]链表为空,则遍历FreePageLists[0]到FreePageLists[n-2]中的链表,以判断是否存在两个分配单元描述符,其对应的空间之和等于n。若找到,则将找到的分配单元描述符返回给请求者,同时更新NvmDescriptor结构中的FreePageNumber字段。即,执行了组合分配的策略。
Step5,若4)步骤查找失败,且n<127,则从FreePageLists[n]开始查找,直到在FreePageLists数组中找到一个非空的链表。若找不到或n等于127,则转向7)执行。
Step6,若在FreePageLists数组中找到一个非空的链表,则从其中取出一个分配单元描述符,并对其所表示的连续空间按照n的大小进行切割。在切割的过程中,会从分配单元描述符内存池中申请一个空闲的分配单元描述符,以表示切割后剩余的空间,并根据剩余空间的大小将其加入到FreePageLists中的某个链表。最后,将原来的分配单元描述符返回给请求者,同时更新NvmDescriptor结构中的FreePageNumber字段。上述过程,即切割分配。
Step7,根据n的大小,确定在FreePageTrees中的哪棵树内进行分配。
Step8,若找到的树FreePageTrees[m]不为空,则根据n的值,在树中进行查找。若能找到一个分配单元描述符,其对应的空间大小正好是n个页框,则取出该分配单元描述符并将其返回给请求者,同时更新NvmDescriptor结构中的FreePageNumber字段。即,执行了确切分配的策略。
Step9,若7)中找到的树为空,或8)中未找到上述分配单元描述符,则遍历FreePageLists[0]到FreePageTrees[m],以判断是否存在两个分配单元描述符,其对应的空间之和等于n。若找到,则将找到的分配单元描述符返回给请求者,同时更新NvmDescriptor结构中的FreePageNumber字段。即,执行了组合分配的策略。
Step10,若9)执行失败,则从FreePageTrees[m]开始遍历,直到找到一个分配单元描述符,其对应的空间大小大于n个页框。
Step11,若找到一个分配单元描述符满足10)的要求,则对该分配单元描述符进行切割。在切割的过程中,会从分配单元描述符内存池中申请一个空闲的分配单元描述符,以表示切割后剩余的空间,并根据剩余空间的大小将其加入到FreePageLists中的某个链表或FreePageTrees中的某个树。最后,将原来的分配单元描述符返回给请求者,同时更新NvmDescriptor结构中的FreePageNumber字段。上述过程,即切割分配。
Step12,若10)执行失败,则从FreePageTrees[4]内的最大分配单元描述符开始递归查找,直到找到足够的空闲页框为止。最后,会将找到的分配单元描述符返回给请求者,并更新NvmDescriptor结构中的FreePageNumber字段。上述过程,即尽力分配。
具体的,页框的释放流程如下:
1、接收到被释放的连续页框的分配单元描述符后,根据NvmAllocUnitDescriptor结构体的PreSpaceAddress字段和NextSpaceAddress字段,找到与被释放页框物理相邻的两个分配单元描述符。
2、根据找到的分配单元描述符NvmAllocUnitDescriptor的Flags字段,判断其对应的空间是否是空闲的。若不是空闲的,则转入4)执行。
3、若是空闲的,则进行合并操作。即使用一个分配单元描述符,表示合并后的空间。合并时,需要从原来所在的FreePageLists或FreePageTrees中,取下被合并的分配单元描述符;之后,再将合并后的分配单元描述符,按照其空间大小放入FreePageLists或FreePageTrees中,并更新NvmDescriptor结构的FreePageNumber字段。
4、根据释放的分配单元描述符对应的空间大小,将其放入到FreePageLists或FreePageTrees中,并更新NvmDescriptor结构的FreePageNumber字段。
第四,对象描述符的组织与管理
由于存在页框找回,即持久化堆找回的问题,所以必须要记录应用程序创建了哪些持久化堆,以及每个持久化堆又包含了哪些页框。本实施例中,使用对象描述符这种元数据,表示一个持久化堆。对象描述符中会记录持久化堆的标识、持久化堆所拥有的若干连续页框(即对象描述符中的分配单元描述符链表)。本实施例中,会根据每个持久化堆的标识,将所有的对象描述符组织成一棵平衡二叉树,该树的根节点即由NvmDescriptor结构中的NvmObjectDestriptor字段指向。当应用程序新创建一个持久化 堆时,其主要的操作过程如下:
首先,根据NvmDescriptor结构中的NvmObjectTree字段,查找创建者传递而来的对象UUID。若找到UUID,则出错返回。
其次,若找不到UUID,则首先根据NvmObjectDescriptorMemoryPool字段,从对象描述符内存池中申请一个空闲的对象描述符,并存入UUID等信息。
第三,将申请到的对象描述符插入到NvmObjectTree指向的红黑树中。
最后,根据创建者要求的空间大小,申请若干空闲页框,并将申请到的分配单元描述符,加入到NvmObjectDestriptor结构的NvmAllocUnitDescriptorInList链表中。
持久化堆的扩充操作和上述过程类似,只是不用创建新的对象描述符而已。当创建完持久化堆后,就可以将申请的页框映射到进程地址空间。下面描述持久化堆删除的主要步骤。
a,当应用程序要删除一个持久化堆时,需要给出被删堆的标识,即UUID。
b,根据NvmDescriptor结构中的NvmObjectTree字段,查找删除者传递而来的对象UUID。若找不到UUID,则出错返回。
c,找到UUID后,即获得对象描述符后,遍历其NvmAllocUnitDescriptorInList链表。
d,对于上述链表中的每个分配单元描述符,都调用页框释放操作,归还分配单元描述符对应的空间。
e,最后,从NvmObjectTree指向的红黑树中删除对象描述符,并归还给对象描述符内存池。
在执行持久化堆的缩减操作时,需要指定缩减的大小。本实施例主要的缩减过程同删除一个持久化堆类似,只是不需要从树中删除对象描述符。
第五,其他说明
在介绍了内存布局、元数据组织、页框的组织与管理,以及对象描述符的组织与管理后,接下来将对锁和日志这两部分内容进行介绍。
由于持久化堆是用来存放应用程序需要持久化保存的数据或数据结构,因此,在同一个系统中,持久化堆的个数和应用的个数相关。而一个应用,通常只会拥有少量的持久化堆。因此,整个系统中持久化堆的个数相对较少。如前所述,只有当持久化堆内剩余的空闲空间过小或过大时,才会导致持久化堆进行扩容或缩减。换句话说,扩容和缩减的操作次数很少。通常情况下,只有持久化堆的申请、删除、扩容和缩减操作,才会在较大程度上影响持久化内存管理机制的并发性。从上面的分析可以看出,这些操作的次数相对比较少。因此,持久化内存管理机制产生争用的概率较小。所以,本专利方案 采用了简单的粗粒度锁,在上述操作入口处即进行加锁。
另外,为了确保持久化内存管理机制的一致性,特别是为了确保出现系统掉电等故障后的一致性,本专利方案采用了传统的undo类型日志方案。在进行持久化堆的申请、删除、扩容和缩减等操作时,会记录元数据部分的所有修改项。在实施例中,用于保存日志的区域,即持久化内存的第一个页框除去NvmDescriptor结构的部分。NvmDescriptor结构占据了1千多字节,因此日志区域有近3千字节。而这3千字节,完全能够容纳元数据部分的修改项。
实施例二
通过以上的实施方式的描述,本领域的技术人员可以清楚地了解到根据上述实施例的方法可借助软件加必需的通用硬件平台的方式来实现,当然也可以通过硬件,但很多情况下前者是更佳的实施方式。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质(如ROM/RAM、磁碟、光盘)中,包括若干指令用以使得一台终端设备(可以是手机,计算机,服务器,或者网络设备等)执行本发明各个实施例所述的方法。
在本实施例中还提供了一种存储空间管理装置,该装置用于实现上述实施例及优选实施方式,已经进行过说明的不再赘述。如以下所使用的,术语“模块”可以实现预定功能的软件和/或硬件的组合。尽管以下实施例所描述的装置较佳地以软件来实现,但是硬件,或者软件和硬件的组合的实现也是可能并被构想的。
图8是根据本发明实施例的存储空间管理装置的结构框图,如图8所示,该装置包括:第一接收模块82,获取模块84,第一查询模块86和分配模块88,其中,
第一接收模块82,用于接收应用程序的内存空间请求;
获取模块84,与第一接收模块82建立电连接,用于获取内存空间请求中所请求的空闲页框数目;
第一查询模块86,与获取模块84建立电连接,用于依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;
分配模块88,与第一查询模块86建立电连接,用于将连续空闲存储空间分配给应用程序。
进一步地,图9是根据本发明实施例的一种存储空间管理装置的结构框图,如图9所示,在空闲页框组织包括:页框链表或树,页框链表或树包括:至少一个分配单元描述符,至少一个分配单元描述符用于描述连续存储空间的存储状态以及连续存储空间对应的页框的起始地址和长度的情况下,第一查询模块86包括:查询单元861,第一匹配 单元862和第二匹配单元863,其中,
查询单元861,用于查询页框链表或树中的至少一个分配单元描述符;
第一匹配单元862,与查询单元861建立电连接,用于将至少一个分配单元描述符中对应的连续空闲存储空间的大小,与应用程序所请求的空闲页框数目对应的连续空闲存储空间进行匹配,查询是否存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;
第二匹配单元863,与第一匹配单元862建立电连接,用于若存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间,则提取连续空闲存储空间作为分配至空闲页框数目对应的连续空闲存储空间;其中,连续存储空间的存储状态包括:已分配和空闲。
进一步地,图10是根据本发明实施例的另一种存储空间管理装置的结构框图,如图10所示,分配模块88包括:第一分配单元881,判断单元882,第二分配单元883,空间查询单元884,空间切割单元885,第三分配单元886,或第四分配单元887,其中,
第一分配单元881,用于在页框链表或树中的连续空闲存储空间的大小等于空闲页框数目对应的连续空闲存储空间大小的情况下,将连续空闲存储空间分配给应用程序;
或者,
判断单元882,用于在页框链表或树中的连续空闲存储空间的大小小于空闲页框数目对应的连续空闲存储空间大小的情况下,在页框链表或树中查询N个连续空闲存储空间,判断N个连续空闲存储空间是否与空闲页框数目对应的连续空闲存储空间大小相等,N为整数,且大于1;
第二分配单元883,与判断单元882建立电连接,用于在判断结果为是的情况下,将N个连续空闲存储空间分配给应用程序。
进一步地,分配模块88还包括:空间查询单元884,用于在N个连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间的情况下,在页框链表或树中查找大于空闲页框数目对应的连续空闲存储空间大小的第一连续空闲存储空间;
空间切割单元885,与空间查询单元884建立电连接,用于在得到第一连续空闲存储空间的情况下,对第一连续空闲存储空间进行切割,得到与空闲页框数目对应的连续空闲存储空间大小相等的第二连续空闲存储空间;
第三分配单元886,与空间切割单元885建立电连接,用于将第二连续空闲存储空间分配给应用程序;其中,将第一连续空闲存储空间切割后的剩余连续空闲存储空间归还至页框链表或树;
或者,
第四分配单元887,用于在页框链表或树中最大的连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间的情况下,在空闲页框链表或树中查询是否存在小于最大连续空闲存储空间的连续存储空间,且连续存储空间的大小与空闲页框数目对应的连续空闲存储空间匹配,若连续存储空间小于空闲页框数目对应的连续空闲存储空间,则在空闲页框链表或树中查询是否存在小于连续空闲存储空间的连续存储空间,直至查询得到与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间,或,提示当前没有能够与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间。
进一步地,图11是根据本发明实施例的又一种存储空间管理装置的结构框图,如图11所示,该存储空间管理装置还包括:第二接收模块1100和第二查询模块1101,其中
第二接收模块1100,用于在将连续空闲存储空间分配给应用程序之后,接收应用程序的持久化内存请求,持久化内存请求用于指示查询应用程序预先存储的数据;
第二查询模块1101,与第二接收模块1100建立电连接关系,用于依据持久化内存请求,通过内存系统中的对象描述符进行查询,得到应用程序预先存储的数据;其中,对象描述符用于指示包含至少一个分配单元描述符的页框链表或树。
需要说明的是,上述各个模块是可以通过软件或硬件来实现的,对于后者,可以通过以下方式实现,但不限于此:上述模块均位于同一处理器中;或者,上述模块分别位于多个处理器中。
本发明的实施例还提供了一种存储介质。可选地,在本实施例中,上述存储介质可以被设置为存储用于执行以下步骤的程序代码:
S1,接收应用程序的内存空间请求;
S2,获取内存空间请求中所请求的空闲页框数目;
S3,依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;
S4,将连续空闲存储空间分配给应用程序。
可选地,存储介质还被设置为存储用于执行以下步骤的程序代码:在空闲页框组织包括:页框链表或树,页框链表或树包括:至少一个分配单元描述符,至少一个分配单元描述符用于描述连续存储空间的存储状态以及连续存储空间对应的页框的起始地址和长度的情况下,依据空闲页框数目查询空闲页框组织,获取与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间的步骤包括:
S1,查询页框链表或树中的至少一个分配单元描述符;
S2,将至少一个分配单元描述符中对应的连续空闲存储空间的大小,与应用程序所 请求的空闲页框数目对应的连续空闲存储空间进行匹配,查询是否存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间;其中,连续存储空间的存储状态包括:已分配和空闲;
S3,若存在与空闲页框数目对应的连续空闲存储空间大小相等的连续空闲存储空间,则提取连续空闲存储空间作为分配至空闲页框数目对应的连续空闲存储空间。
可选地,在本实施例中,上述存储介质可以包括但不限于:U盘、只读存储器(ROM,Read-Only Memory)、随机存取存储器(RAM,Random Access Memory)、移动硬盘、磁碟或者光盘等各种可以存储程序代码的介质。
可选地,在本实施例中,处理器根据存储介质中已存储的程序代码执行将连续空闲存储空间分配给应用程序的步骤包括:若页框链表或树中的连续空闲存储空间的大小等于空闲页框数目对应的连续空闲存储空间大小,则将连续空闲存储空间分配给应用程序;若页框链表或树中的连续空闲存储空间的大小小于空闲页框数目对应的连续空闲存储空间大小,则在页框链表或树中查询N个连续空闲存储空间,判断N个连续空闲存储空间是否与空闲页框数目对应的连续空闲存储空间大小相等,N为整数,且大于1;在判断结果为是的情况下,将N个连续空闲存储空间分配给应用程序。
可选地,在本实施例中,处理器根据存储介质中已存储的程序代码执行若N个连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间,则在页框链表或树中查找大于空闲页框数目对应的连续空闲存储空间大小的第一连续空闲存储空间;若得到第一连续空闲存储空间,则对第一连续空闲存储空间进行切割,得到与空闲页框数目对应的连续空闲存储空间大小相等的第二连续空闲存储空间;将第二连续空闲存储空间分配给应用程序;其中,将第一连续空闲存储空间切割后的剩余连续空闲存储空间归还至页框链表或树;若页框链表或树中最大的连续空闲存储空间小于空闲页框数目对应的连续空闲存储空间,则在空闲页框链表或树中查询是否存在小于最大连续空闲存储空间的连续存储空间,且连续存储空间的大小与空闲页框数目对应的连续空闲存储空间匹配,若连续存储空间小于空闲页框数目对应的连续空闲存储空间,则在空闲页框链表或树中查询是否存在小于连续空闲存储空间的连续存储空间,直至查询得到与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间,或,提示当前没有能够与空闲页框数目对应的连续空闲存储空间匹配的连续空闲存储空间。
可选地,在本实施例中,处理器根据存储介质中已存储的程序代码执行将连续空闲存储空间分配给应用程序之后,本实施例提供的存储空间管理方法还包括:接收应用程序的持久化内存请求,持久化内存请求用于指示查询应用程序预先存储的数据;依据持久化内存请求,通过内存系统中的对象描述符进行查询,得到应用程序预先存储的数据;其中,对象描述符用于指示包含至少一个分配单元描述符的页框链表或树。
可选地,本实施例中的具体示例可以参考上述实施例及可选实施方式中所描述的示 例,本实施例在此不再赘述。
显然,本领域的技术人员应该明白,上述的本发明的各模块或各步骤可以用通用的计算装置来实现,它们可以集中在单个的计算装置上,或者分布在多个计算装置所组成的网络上,可选地,它们可以用计算装置可执行的程序代码来实现,从而,可以将它们存储在存储装置中由计算装置来执行,并且在某些情况下,可以以不同于此处的顺序执行所示出或描述的步骤,或者将它们分别制作成各个集成电路模块,或者将它们中的多个模块或步骤制作成单个集成电路模块来实现。这样,本发明不限制于任何特定的硬件和软件结合。
以上所述仅为本发明的优选实施例而已,并不用于限制本发明,对于本领域的技术人员来说,本发明可以有各种更改和变化。凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。