专利名称:一种内存管理方法
技术领域:
本发明涉及一种内存管理方法,尤其涉及一种数据通信设备中的内存管理方法。
背景技术:
数据通信设备支持的业务种类非常众多,而各种业务种类的数据结构内存特征大小各不相同。为了满足各种内存特征大小的申请、释放操作,通常使用一种经典的内存管理方法—伙伴算法。
该算法将空闲内存分为多个块组,每组中块的大小为2的幂次方字节,比如第0组中块的大小都为32字节,第1组中块的大小都为64字节,第n组中块的大小都为32*2^n字节。也就是说,每一组中块的大小都相同且这些相同大小的块形成一个链表。当申请65字节内存时,该算法先从128字节的块组的空闲链表中寻找,看是否存在空闲块。如果有就直接分配;如果没有就继续查找下一个更大的块。具体地说,就是在256字节的块组的空闲链表中寻找,如果存在这样的空闲块,将该空闲块分为两等份,一份分配出去,另一份插入到128字节块组的空闲链中。如果256字节的块组也没有空闲块,则继续找更大的块组,即512字节的块组。如果存在空闲块,则将512字节分配出128字节,剩余384字节分为256字节插入256字节块组和128字节插入128字节块组。以此类推。如果最大块组还没有空闲块则放弃分配。内存释放是上述过程的逆过程,即两块大小相等、物理地址连续的内存可以进行合并,合并后的内存还可以与相邻块合并时则继续合并。
这种内存管理方法可以满足各种内存特征大小的申请和释放,但是存在内存使用效率不足的缺点,根据算法原理,平均情形内存使用效率只有75%,如果某些关键数据结构内存特征大小处于特殊值比如65时,内存使用效率就下降到只有50%多一点了。
发明内容
本发明要解决的技术问题是提出一种内存管理方法,该方法能够有效地提高内存的使用效率。
为了解决上述技术问题,本发明提供了一种内存管理方法,包括下述步骤(a)设定一个最小单元,使空闲内存块的大小均为该最小单元p倍,p为正整数,同时定义多个块组,每个块组对应于一个周内存大小标识的区间且各区间互不重叠,每个块组可包括多个大小不同的空闲内存块;(b)使用时,将内存划分为一个或多个空闲内存块,在内存中维护每个块组当前所包括的空闲内存块的信息,以及每个内存块的大小和使用情况的信息;(c)内存管理模块收到内存分配请求后,确定能满足该请求的最小空闲内存块的大小,然后从那些可能具有该最小空闲内存块或更大空闲内存块的块组中寻找一个能满足该请求的空闲内存块进行分配,如找到,执行下一步,否则,此次申请失败,结束;(d)如果找到的空闲内存块即为所述最小空闲内存块,执行步骤(e),否则,其大小要大于所述最小空闲内存块的大小,执行步骤(f);(e)将找到的空闲内存块的可用区间分配给用户使用,更新该内存块的信息以及其所属块组的空闲内存块的信息,此次申请成功,结束;(f)将找到的空闲内存块拆分为最小空闲内存块和余下部分构成的空闲内存块,将最小空闲内存块的可用区间分配给用户使用,并更新该两个内存块的信息及其所属块组的空闲内存块的信息,此次申请成功,结束。
进一步地,上述内存管理方法还可具有以下特点还包括以下释放内存和合并空闲内存块的步骤(h)内存管理模块收到释放内存请求,根据请求中的参数找到待处理的内存块;
(i)判断与所述待处理的内存块相邻的前一个和后一个内存块是否为空闲内存块,如果是,执行下一步,否则,执行步骤(k);(j)将所述待处理的内存块与其相邻的前一个和/或后一个空闲内存块合并,将该合并的空闲内存块作为新的待处理内存块,更新被合并的空闲内存块所属块组的空闲内存块的信息;(k)更新所述待处理内存块的信息及其所属块组的空闲内存块的信息,结束。
进一步地,上述内存管理方法还可具有以下特点所述步骤(c)中,所述内存管理模块在查找能满足所述内存分配请求的空闲内存块时,是从所述最小空闲内存块所属的块组或其下一个块组开始查找,如果在该块组中找不到,再向到其下一个块组去查找,如此依次查找。
进一步地,上述内存管理方法还可具有以下特点所述步骤(a)定义块组的区间时,使各个块组对应的内存大小的区间合在一起覆盖了用户可能申请使用的内存大小。
进一步地,上述内存管理方法还可具有以下特点所述步骤(a)按以下方式定义块组的区间第n个块组对应区间内的内存大小为所述最小单元的2n倍到2(n+1)-1倍,n=0,1,2,……。
进一步地,上述内存管理方法还可具有以下特点所述步骤(b)还事先建立p值与开始查找的块组的块组号的映射关系,在所述步骤(c)中可根据最小空闲内存块的p值直接确定开始查找的块组。
进一步地,上述内存管理方法还可具有以下特点所述步骤(b)中,是为每个块组维护一个空闲内存块链表,链表中的节点指示了对应块组当前所包括的所有空闲内存块及其位置信息,且还为每个内存块建立了一个用于记录其信息的内存管理结构,该结构中至少包含该内存块的大小和使用标志的信息。
进一步地,上述内存管理方法还可具有以下特点所述空闲内存块链表为双向链表,链表中每一个中间节点均保存了其前、后相邻节点的地址信息。
进一步地,上述内存管理方法还可具有以下特点所述空闲内存块链表的第一个节点均建立在专用内存区,其第二个及以后的节点均建立在该节点所指示的空闲内存块中。
进一步地,上述内存管理方法还可具有以下特点所述步骤(b)为每个内存块建立的内存管理结构设置在每个内存块内的起始位置,所述步骤(c)中收到大小为size的内存分配请求后,需要先将size加上该内存管理结构所需的大小作为待分配的最小内存大小,再确定能满足该请求的最小空闲内存块的大小。
进一步地,上述内存管理方法还可具有以下特点所述步骤(c)在确定了能满足该请求的最小空闲内存块的大小后,在该最小空闲内存块也是其所属块组中最小的空闲内存块时,查找其所属块组的空闲内存块链表,否则查找其所属块组的下一个块组的空闲内存块链表,从查找的链表中取出存在的第一个空闲内存块进行分配。
进一步地,上述内存管理方法还可具有以下特点所述为每个内存块建立的内存管理结构中还包括地址相邻的前一个内存块的位置信息和/或是否存在地址相邻的后一内存块的标志信息。
进一步地,上述内存管理方法还可具有以下特点当空闲内存块被分配给用户使用而更新其所属块组的空闲内存块的信息时,是将该块组的空闲内存块链表中对应于该空闲内存块的节点从该链表中删除,当因拆分、释放而有新的空闲内存块生成而更新该新的空闲内存块所属块组的空闲内存块的信息时,是在该块组的空闲内存块链表中加入用于指示该空闲内存块的节点。
与现有技术相比,本发明具有如下显著优点(1)本发明极大地改进了伙伴算法内存使用效率低的缺点,并且使得内存使用效率与关键数据结构内存特征大小关系较小采用接近用户所需大小进行内存的分配,每次内存分配的浪费在最坏情形下也只是接近一个最小内存块,只要申请内存的平均值比最小内存块大很多,则即使在最坏情形下的内存使用效率也能大大超过伙伴算法的平均内存使用效率;(2)本发明所述的内存管理方法的内存申请无需伙伴算法的多次分片,内存释放无需伙伴算法的多次合并,在效率上也得到了进一步的改进。
图1为本发明实施例块组和空闲内存块的构造及逻辑关系示意图;图2为本发明实施例块组、空闲内存块、已分配内存块基本数据结构示意图;图3为本发明实施例内存分配的流程图;图4为本发明实施例内存释放的流程图具体实施方式
下面结合附图和具体实施例对本发明作进一步的介绍,但不作为对本发明的限定。
在本实施例中,首先确定一个空闲内存块的最小单元,空闲内存块的大小均为该最小单元p倍,p为正整数。同时,定义多个块组,每个块组对应于一个用内存大小标识的区间,不同块组的区间互不重叠,使得这些块组的内存大小区间合在一起可以覆盖用户可能申请使用的内存大小,这样申请内存时总可以找到相应的块组。每个块组可以包括多个大小不等但在该块组区间内的内存块,反之,每个内存块按其大小归属于一个块组。
参考图1,块1表示大小为确定的最小单元的空闲内存块,块2表示大小为最小单元2倍的空闲内存块,以此类推……。根据空闲内存块的大小所属的区间将其归属到该区间对应的块组中。本实施例中,第0个块组中空闲内存块的大小都是最小单元,第1个块组中空闲内存块的大小是最小单元的2倍或3倍,第2个块组中空闲内存块的大小都为最小单元的4倍、5倍、6倍或7倍,……第n个块组中空闲内存块的大小都为最小单元的2n倍到2(n+1)-1倍,n可以根据用户的实际需求确定,应注意的是,这里的区间也可以采用其它的划分方式。
图2是本实施例块组、空闲内存块和已分配内存块基本数据结构示意图。本实施例在用户可用内存中的每个内存块的起始位置设置了一个内存管理结构,用于记录该内存块的大小(size=最小单元的倍数)、地址相邻的前一个内存块的位置(prev_nbr_addr)(指起始地址)、是否存在地址相邻的后一内存块的标志(have_next_nbr),以及本内存块是否使用的标志(used_flag)等信息。将这些信息直接存放在内存块的起始位置,就不必建立保存以上信息的映射表并在映射表和内存块之间来回跳转和在映射表中逐一查找,可以很方便地获取内存块的各种信息。实施例中所提的内存块的大小包括了其内存管理结构所占用的空间。
以上内存管理结构中的内容是可以变化的,例如,在另一实施例中,后一内存块标记可以不需要,直接根据地址可以判断出来。而前一个相邻内存块的地址只是在内存释放合并时才需要,仅仅内存申请或者采用定时合并方式是不需要的。
为了便于在用户内存的申请时快速找到需要的空闲内存块,本实施例方法为每个块组均维护一个双向的空闲内存块链表,用于指示该块组包含的所有空闲内存块及其位置信息。每个双向空闲链表由相互链接的一个或多个节点组成。如图2所示,本实施例将所有双向空闲内存链表的第一个节点集中设置在内存的一个专用区域,查询时可以从该区域中找到相应块组的第一个节点,该节点应保存有该链表对应的块组的标识。第一个节点后的所有节点直接设置在该节点所指示的空闲内存块中,其所在位置即该空闲内存块的位置,无需额外的指示信息。在每个节点上均包括第一指针和第二指针,第一指针为前一个节点的地址,第二指针为后一个节点的地址,第一个节点的第一指针和最后一个节点的第二指针设为空(NULL)。通过将节点设置在空闲内存块中,可以利用用户内存空间完成双向链表的构建,因而有效地节约了内存空间。
如图2所示,为块组mm_unit[1](即第一个块组)维护了一个双向空闲内存块链表,用于指示该块组中包含的大小为最小单元2倍或3倍的空闲内存块,图中该链表包括3个节点。类似地,要为块组mm_unit[n]维护一个双向空闲链表,用于指示该块组中包含的大小为最小单元2n倍或2n+1倍、....、2(n+1)-1倍的空闲内存块。
双向链表的设置使得可以很方便地从链表中删除一个节点,当要删除一个空闲内存块对应的节点N时,只要根据该空闲内存块中保存的节点N的第一和第二指针找到其前后节点,并将其前一个节点的第二指针修改为节点N的第二指针,将其后一个节点的第一指针修改为节点N的第一指针就可以了,无需从头访问链表。在链表中增加一个节点时,在本实施方式中是插入到原链表的第一个节点之后。但在另一实施例中,也可以接在原链表最后一个节点上。
图3为本发明实施例内存分配方法的流程图,其中的操作都是由内存管理模块完成的,如图所示,该方法包括以下步骤步骤100,使用时,先将用户可用的空闲内存划分为多个空闲内存块,常用的是将可用的空闲内存划分为内存管理模块设定的最大空闲内存块,将这些最大空闲内存块链入最大块组的多向链表中,但也可以划分为属于不同块组的多个空闲块;本实施例采用最小单元的1倍到2(n+1)-1倍这种方式来设置块组,内存管理模块只需要设置最小单元和n,根据具体的用户环境选择合适的值就可以要满足这个要求,对超过设置的最大空闲内存块大小的内存需求可以由内存管理模块先进行拆分。
另外,为了提高内存申请的效率,还事先建立p与大小为最小单元p倍的空闲内存块所属块组号的映射关系。
步骤101内存管理模块收到大小为size内存分配请求后,将size加上内存管理结构所需的大小,得到待分配的最小内存大小;本实施例中,由于内存管理结构是在用户内存块的内部,所以最终分配出的内存块中隐含了一个管理内存结构,在计算所需大小时要计入内存管理结构所需的大小。
步骤102根据待分配的最小内存的大小,计算出能容纳该最小内存的空闲内存块大小应为最小单元的p1倍;
步骤103根据事先设定的p与块组号的映射关系,找到相应的块组;本实施例中,p并不一定是和大小为p倍最小单元的空闲内存块所属块组的块组号间建立映射,为了保证查找的块组中的空闲内存块都能大于或等于待分配的最小内存的大小,以简化流程。在映射时,如果p倍最小单元是某个块组的最小空闲内存块的大小,则在该p值与大小为p倍最小单元的空闲内存块所属块组的块组号间建立映射,而当p倍最小单元不是块组所包括的最小空闲内存块的大小时,则与该p值建立映射的块组号,其对应块组是大小为p倍最小单元的空闲内存块所属块组的下一个块组(文中所说的某一个块组A的“下一个”块组是指与块组A的区间相邻,且其包括的空闲内存块大于块组A包括的空闲内存块的块组)。
步骤104查询该块组的双向空闲链表中是否存在空闲内存块,如果存在,则执行步骤105,如果不存在,则执行步骤110;步骤105从该空闲链表中取出其指示的第一个空闲内存块;步骤106判断该空闲内存块的大小是否大于p1倍的最小单元,如果是,则执行下一步骤107,如果不是,则执行步骤109;步骤107将空闲内存块拆分为两块,第一个内存块的内存大小为p1倍最小单元,修改该块内存管理结构中的相应内容为内存大小size=p1,地址相邻的后一内存块的存在标记have_next_nbr=1,使用标记used_flag=1,地址相邻的前一个内存块的位置prev_nbr_addr=原值;剩余的第二个内存块的管理结构中的相应内容也相应更改为内存大小size=原倍数-p1,地址相邻的前一个内存块的位置prev_nbr_addr=刚拆分的第一个内存块地址,地址相邻的后一内存块的存在标记have_next_nbr=原值,使用标记used_flag=0;步骤108,根据分出的第二个内存块的内存大小定位到其所属的块组号,在该块组的双向空闲链表后加上用于指示该内存块的节点,并将分出的第一个内存块的用户区间分配给用户使用,从双向链表中删除该内存块对应的节点,本次申请成功,结束;步骤109将该空闲内存块的用户区间分配给用户使用,并从双向链表中删除该内存块对应的节点,本次申请成功,结束;步骤110判断是否存在下一个块组,如果存在,则执行步骤104,如果不存在,则执行步骤111;步骤111;内存申请失败,作错误处理,结束。
图4为本实施例内存释放的流程图,各个操作是由内存管理模块执行的,如图所示,该流程包括以下步骤步骤201,内存管理模块收到释放内存请求,输入参数为待释放内存地址,待释放内存减去管理结构所需大小得一地址,定义为待处理内存;步骤202根据待处理内存块携带的管理结构判断其是否存在相邻且空闲的前一个内存块,如果存在,执行步骤203,如果不存在,则直接执行步骤204;步骤203从所述前一个空闲内存块所属块组的空闲内存块链表中删除该内存块对应的节点,将待处理的内存块和该前一个空闲内存块合并,设置合并后内存块的内存管理结构的内容为内存大小size=两者之和、地址相邻的后一内存块的存在标记have_next_nbr=待处理内存块的原值,使用标记used_flag=0,地址相邻的前一个内存块的位置prev_nbr_addr=所述前一个空闲内存块的原值,然后将合并后的内存块设置为新的待处理内存,执行步骤204;步骤204判断待处理内存是否存在相邻且空闲的后一块内存,如果存在,则执行步骤205,如果不存在,则执行步骤206;步骤205将所述后一个空闲内存块对应的链表节点从其所属块组的空闲内存块链表中删除,将待处理的内存块和该后一个空闲内存块合并,设置合并后内存块的内存管理结构的内容为内存大小size=两者之和、地址相邻的后一内存块的存在标记have_next_nbr=后一个内存块的原值,使用标记used_flag=0,地址相邻的前一个内存块的位置prev_nbr_addr=待处理内存块的原值,然后将合并后的内存块设置为新的待处理内存,执行步骤206;步骤206根据待处理内存块的大小确定其所属的块组,在该块组的空闲内存块链表中加入指示该待处理内存块的节点,结束。
在上述实施例的基础上,本发明还可以有各种变换,这些变换应当属于本发明的保护范围之内。
例如对空闲内存块的合并是因为一直拆分不合并的话,会导致空闲内存块越来越小,当用户申请较大内存时就会申请不成功,而实际上可用内存还很多,所以内存合并是必须的,数学上可以证明实施例中采用的每次释放时与前一个、后一个空闲块合并就可以保证合并无遗漏了。但是,上述合并的方式并不是唯一的,在另一实施例中,也可以采用定时合并的方式,即在定时器到时,搜索内存中的空闲内存块,可以按顺序将可合并的空闲内存块都合并在一起。
又如,本实施例在查找空闲内存块时,是从能容纳计算出的最小内存的空闲内存块所属块组开始查找的,但在另一实施例中,是先从最大空闲块组开始寻找,找不到再继续找次大空闲块组,直到所属块组,还可以采用其他顺序。事先由内存管理模块将查找顺序设定好就可以了。
又如在分配空闲内存时,确定了要查找的块组后,上述实施例是在该块组的链表中找到第一个空闲内存块就进行分配,在另一实施例中,也可以先查找在块组的链表中是否存在刚好能容纳该申请内存的大小为最小单元p倍的空闲内存块,如果没有再对第一个空闲内存块进行分配。
权利要求
1.一种内存管理方法,包括下述步骤(a)设定一个最小单元,使空闲内存块的大小均为该最小单元p倍,p为正整数,同时定义多个块组,每个块组对应于一个用内存大小标识的区间且各区间互不重叠,每个块组可包括多个大小不同的空闲内存块;(b)使用时,将内存划分为一个或多个空闲内存块,在内存中维护每个块组当前所包括的空闲内存块的信息,以及每个内存块的大小和使用情况的信息;(c)内存管理模块收到内存分配请求后,确定能满足该请求的最小空闲内存块的大小,然后从那些可能具有该最小空闲内存块或更大空闲内存块的块组中寻找一个能满足该请求的空闲内存块进行分配,如找到,执行下一步,否则,此次申请失败,结束;(d)如果找到的空闲内存块即为所述最小空闲内存块,执行步骤(e),否则,其大小要大于所述最小空闲内存块的大小,执行步骤(f);(e)将找到的空闲内存块的可用区间分配给用户使用,更新该内存块的信息以及其所属块组的空闲内存块的信息,此次申请成功,结束;(f)将找到的空闲内存块拆分为最小空闲内存块和余下部分构成的空闲内存块,将最小空闲内存块的可用区间分配给用户使用,并更新该两个内存块的信息及其所属块组的空闲内存块的信息,此次申请成功,结束。
2.如权利要求1所述的内存管理方法,其特征在于,还包括以下释放内存和合并空闲内存块的步骤(h)内存管理模块收到释放内存请求,根据请求中的参数找到待处理的内存块;(i)判断与所述待处理的内存块相邻的前一个和后一个内存块是否为空闲内存块,如果是,执行下一步,否则,执行步骤(k);(j)将所述待处理的内存块与其相邻的前一个和/或后一个空闲内存块合并,将该合并的空闲内存块作为新的待处理内存块,更新被合并的空闲内存块所属块组的空闲内存块的信息;(k)更新所述待处理内存块的信息及其所属块组的空闲内存块的信息,结束。
3.如权利要求2所述的内存管理方法,其特征在于,所述步骤(c)中,所述内存管理模块在查找能满足所述内存分配请求的空闲内存块时,是从所述最小空闲内存块所属的块组或其下一个块组开始查找,如果在该块组中找不到,再向到其下一个块组去查找,如此依次查找。
4.如权利要求1或2所述的内存管理方法,其特征在于,所述步骤(a)定义块组的区间时,使各个块组对应的内存大小的区间合在一起覆盖了用户可能申请使用的内存大小。
5.如权利要求1或2所述的内存管理方法,其特征在于,所述步骤(a)按以下方式定义块组的区间第n个块组对应区间内的内存大小为所述最小单元的2n倍到2(n+1)-1倍,n=0,1,2,……。
6.如权利要求3所述的内存管理方法,其特征在于,所述步骤(b)还事先建立p值与开始查找的块组的块组号的映射关系,在所述步骤(c)中可根据最小空闲内存块的p值直接确定开始查找的块组。
7.如权利要求1或2所述的内存管理方法,其特征在于,所述步骤(b)中,是为每个块组维护一个空闲内存块链表,链表中的节点指示了对应块组当前所包括的所有空闲内存块及其位置信息,且还为每个内存块建立了一个用于记录其信息的内存管理结构,该结构中至少包含该内存块的大小和使用标志的信息。
8.如权利要求7所述的内存管理方法,其特征在于,所述空闲内存块链表为双向链表,链表中每一个中间节点均保存了其前、后相邻节点的地址信息。
9.如权利要求7所述的内存管理方法,其特征在于,所述空闲内存块链表的第一个节点均建立在专用内存区,其第二个及以后的节点均建立在该节点所指示的空闲内存块中。
10.如权利要求7所述的内存管理方法,其特征在于,所述步骤(b)为每个内存块建立的内存管理结构设置在每个内存块内的起始位置,所述步骤(c)中收到大小为size的内存分配请求后,需要先将size加上该内存管理结构所需的大小作为待分配的最小内存大小,再确定能满足该请求的最小空闲内存块的大小。
11.如权利要求7所述的内存管理方法,其特征在于,所述步骤(c)在确定了能满足该请求的最小空闲内存块的大小后,在该最小空闲内存块也是其所属块组中最小的空闲内存块时,查找其所属块组的空闲内存块链表,否则查找其所属块组的下一个块组的空闲内存块链表,从查找的链表中取出存在的第一个空闲内存块进行分配。
12.如权利要求7所述的内存管理方法,其特征在于,所述为每个内存块建立的内存管理结构中还包括地址相邻的前一个内存块的位置信息和/或是否存在地址相邻的后一内存块的标志信息。
13.如权利要求7所述的内存管理方法,其特征在于,当空闲内存块被分配给用户使用而更新其所属块组的空闲内存块的信息时,是将该块组的空闲内存块链表中对应于该空闲内存块的节点从该链表中删除,当因拆分、释放而有新的空闲内存块生成而更新该新的空闲内存块所属块组的空闲内存块的信息时,是在该块组的空闲内存块链表中加入用于指示该空闲内存块的节点。
全文摘要
本发明公开了一种内存管理方法,先设定一个空闲内存块的最小单元,并定义多个块组,每个块组可包括多个大小不同的空闲内存块;使用时,维护每个块组当前所包括的所有空闲内存块的信息及每个内存块的大小和使用情况信息;收到内存分配请求后,确定能满足该请求的最小空闲内存块,然后在可能具有满足该请求的空闲内存块的块组中寻找一个可满足该请求的空闲内存块,如找到的空闲内存块大小等于该最小空闲内存块,则直接将其分配给用户并更新相关信息,否则将其拆分为最小空闲内存块和剩余部分构成的内存块,将最小空闲内存块分配给用户,并更新该两个内存块的信息及其所属块组的空闲内存块的信息。本发明方法能够有效地提高内存的使用效率。
文档编号G06F12/02GK1963788SQ20051011767
公开日2007年5月16日 申请日期2005年11月8日 优先权日2005年11月8日
发明者张应平, 沈晓峰 申请人:中兴通讯股份有限公司