本发明属于操作系统技术领域,特别是涉及一种内存分配调度的方法和装置。
背景技术:
在LINUX系统中,OS只负责处理应用层的内存请求,但却不负责内存的回收,在上层应用对内存资源的使用较为频繁时,经常会造成内存泄漏和内存溢出等问题。其中,在申请内存和释放内存方式方面,堆和栈有着很大的不同。栈是编译器自动申请的,例如在主函数里面,要声明一个int变量a,那么编译器就自动开辟一块内存来存放变量a。而堆则不相同,是由程序员手动申请的,只要程序员感觉程序此处需要用到多大的内存空间,那么就使用malloc或者new来申请固定大小的内存使用。栈的空间在程序结束的时候由系统或者编译器自动释放,而堆则在程序结束前由程序员手动使用free或delete释放,或者忘记手动释放,由系统在程序结束的时候自动回收。由于内存区域总是有限的,不能无限制地分配下去,而且程序应尽量节省资源,所以当分配的内存区域不用时,则要释放它,以便其他的变量或程序使用。
一般我们常说的内存泄漏是指堆内存的泄漏,堆内存使用完后必须进行释放,否则这块内存就不能再次使用,我们就说这块内存泄漏了;内存溢出即用户在对其数据缓冲区操作时,超过了其缓冲区的边界,尤其是对缓冲区进行写操作时,缓冲区的溢出很可能导致程序的异常。
技术实现要素:
为解决上述问题,本发明提供了一种内存分配调度的方法和装置,能够对系统内存进行统一的分配、管理、调度和监测,来实现内存的合理利用与回收,避免内存泄露或溢出导致的程序异常。
本发明提供的一种内存分配调度的方法,包括:
获取内存块并对其初始化;
利用内存分配API从所述内存块中分配内存,并向已分配的内存中添加控制信息;
利用audit检测线程每隔预设时间对已分配的内存进行检测,如果超时之后仍未释放则产生内存告警;
利用内存释放API释放使用完的内存。
优选的,在上述内存分配调度的方法中,
所述利用内存分配API从所述内存块中分配内存包括:
计算所需内存的大小;
设置functionbacktrace的级别;
设置内存的使用时间;
检索内存链表,返回内存地址。
优选的,在上述内存分配调度的方法中,
所述检索内存链表,返回内存地址包括:
如果所述内存链表中包含用户所需大小的内存,则直接返回内存地址;
否则将内存进行拆分出用户所需大小的内存,并将剩余的内存插入所述内存链表中。
优选的,在上述内存分配调度的方法中,
在所述利用内存分配API从所述内存块中分配内存之后,还包括:
将分配的内存清零。
优选的,在上述内存分配调度的方法中,
在所述利用内存分配API从所述内存块中分配内存之后,还包括:
利用API将数据从其他地址拷贝到已分配的内存中。
本发明提供的一种内存分配调度的装置,包括:
获取单元,用于获取内存块并对其初始化;
分配单元,用于利用内存分配API从所述内存块中分配内存,并向已分配的内存中添加控制信息;
检测单元,用于利用audit检测线程每隔预设时间对已分配的内存进行检测,如果超时之后仍未释放则产生内存告警;
释放单元,用于利用内存释放API释放使用完的内存。
优选的,在上述内存分配调度的装置中,
所述分配单元包括:
计算部件,用于计算所需内存的大小;
第一设置部件,用于设置functionbacktrace的级别;
第二设置部件,用于设置内存的使用时间;
检索部件,用于检索内存链表,返回内存地址。
优选的,在上述内存分配调度的装置中,
所述检索部件具体用于如果所述内存链表中包含用户所需大小的内存,则直接返回内存地址;否则将内存进行拆分出用户所需大小的内存,并将剩余的内存插入所述内存链表中。
优选的,在上述内存分配调度的装置中,
还包括:
清零单元,用于将分配的内存清零。
优选的,在上述内存分配调度的装置中,
还包括:
拷贝单元,用于利用API将数据从其他地址拷贝到已分配的内存中。
通过上述描述可知,本发明提供的上述内存分配调度的方法和装置,由于该方法包括获取内存块并对其初始化;利用内存分配API从所述内存块中分配内存,并向已分配的内存中添加控制信息;利用audit检测线程每隔预设时间对已分配的内存进行检测,如果超时之后仍未释放则产生内存告警;利用内存释放API释放使用完的内存,因此能够对系统内存进行统一的分配、管理、调度和监测,来实现内存的合理利用与回收,避免内存泄露或溢出导致的程序异常。
附图说明
为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据提供的附图获得其他的附图。
图1为本申请实施例提供的第一种内存分配调度的方法的示意图;
图2为本申请实施例提供的第一种内存分配调度的装置的示意图。
具体实施方式
本发明的核心思想在于提供一种内存分配调度的方法和装置,能够对系统内存进行统一的分配、管理、调度和监测,来实现内存的合理利用与回收,避免内存泄露或溢出导致的程序异常。
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
本申请实施例提供的第一种内存分配调度的方法如图1所示,图1为本申请实施例提供的第一种内存分配调度的方法的示意图,该方法包括如下步骤:
S1:获取内存块并对其初始化;
具体的,在系统启动后,一次性通过OS(操作系统)获取较大的一块内存,并进行初始化。
S2:利用内存分配API从所述内存块中分配内存,并向已分配的内存中添加控制信息;
需要说明的是,上层应用通过专门的内存分配API从该内存块中进行内存申请。根据实际应用中对内存的使用情况,可以将内存分配API分为四类:普通的内存申请、用于关键资源的内存分配、提供额外functionbacktrace(可用于debug)的内存分配和从特定的内存池进行内存申请。每次调用完内存分配API后,用户需要自行判断内存指针是否为NULL:若不为NULL,则内存分配成功;若为NULL,则失败,用户需做相应的逻辑处理。但若是用于关键资源的内存分配失败,系统则会重启,这是和普通类型内存分配最显著的区别,内存分配失败可能是由于系统负载过重导致内存不够用,只有在必要的时候才能进行系统重启;提供额外functionbacktrace的内存分配:这种类型的内存分配可以设置追踪函数调用堆栈的级别,最多可以打印出7级函数,因此有利于理解整个函数调用过程,也便于后期的测试和debug;从特定的内存池进行内存申请,例如内存池为写保护模式(可用于后期测试过程中内存溢出的检测),在申请内存的时候,设置内存写保护(每页内的内存具有相同读写属性),若向具有只读属性的内存写数据,则会触发Segv。内存分配后,用户应该自行去判断内存分配是否真的生效,即判断返回地址是否为NULL。因为对于内存管理器而言,每次分配都会返还一个合法有效地址或是NULL;对于关键类型的分配则不用进行检测,因为分配若失败,内存管理器不会返回任何值,进程直接重启。这里用到的用于内存分配的API如下表1所示。
表1内存分配API表
S3:利用audit检测线程每隔预设时间对已分配的内存进行检测,如果超时之后仍未释放则产生内存告警;
需要说明的是,上一步骤中,在每个内存块中添加了控制信息,以此来判断是否发生内存泄漏、内存溢出以及数据被写坏,进一步的还可以判断具体是overflow还是underflow。这种audit检测线程可以每间隔五分钟检测一次,防止memory overflow/underflow和memory leak的产生,进而提高系统性能。
S4:利用内存释放API释放使用完的内存。
需要说明的是,用户在使用完内存后,通过专门的内存释放API进行释放,则释放的内存会重新加入可用内存链表中,这里用到的内存释放API如下表2所示。
表2内存释放API表
通过上述描述可知,本申请实施例提供的上述内存分配调度的方法,由于包括获取内存块并对其初始化;利用内存分配API从所述内存块中分配内存,并向已分配的内存中添加控制信息;利用audit检测线程每隔预设时间对已分配的内存进行检测,如果超时之后仍未释放则产生内存告警;利用内存释放API释放使用完的内存,因此能够对系统内存进行统一的分配、管理、调度和监测,来实现内存的合理利用与回收,避免内存泄露或溢出导致的程序异常。
本申请实施例提供的第二种内存分配调度的方法,是在上述第一种内存分配调度的方法的基础上,还包括如下技术特征:
所述利用内存分配API从所述内存块中分配内存包括:
计算所需内存的大小;
设置functionbacktrace的级别,最多可以打印7级;
设置内存的使用时间,可以以5分钟为间隔,取值范围为[1,255];
检索内存链表,返回内存地址,而如果内存分配失败,若是普通内存申请,用户做相应的逻辑处理,会产生相应的log,若是用于关键资源的内存申请失败,系统直接重启。
需要说明的是,考虑到API的通用性,以及后期的代码维护,负责内存分配API需要至少以下3种信息:用于保存内存指针的地址,分配成功则指向被分配的内存地址,分配失败则被置为NULL;申请内存的大小;内存使用类型,如内存使用时间(以5分钟为单位)或无时间限制(用enumMEM_USE来定义)。如有需要还可以设置打印函数调用堆栈的级别,以及内存读写属性。
本申请实施例提供的第三种内存分配调度的方法,是在上述第二种内存分配调度的方法的基础上,还包括如下技术特征:
所述检索内存链表,返回内存地址包括:
如果所述内存链表中包含用户所需大小的内存,则直接返回内存地址;
否则将内存进行拆分出用户所需大小的内存,并将剩余的内存插入所述内存链表中。
本申请实施例提供的第四种内存分配调度的方法,是在上述第一种至第三种内存分配调度的方法中任一种的基础上,还包括如下技术特征:
在所述利用内存分配API从所述内存块中分配内存之后,还包括:
将分配的内存清零。
需要说明的是,这只是在特定情况下的一个可选项,如果要往分配的内存写数据,则可以不这样做,因为会浪费CPU时间。
本申请实施例提供的第五种内存分配调度的方法,是在上述第四种内存分配调度的方法的基础上,还包括如下技术特征:
在所述利用内存分配API从所述内存块中分配内存之后,还包括:
利用API将数据从其他地址拷贝到已分配的内存中。
需要说明的是,分配完内存之后,用户一般自己往内存里写数据。但如果数据是固定的,则直接可以利用API来完成内存分配和数据拷贝两个步骤,而无需用户进行拷贝。
本申请实施例提供的第一种内存分配调度的装置如图2所示,图2为本申请实施例提供的第一种内存分配调度的装置的示意图,该装置包括:
获取单元201,用于获取内存块并对其初始化,具体的,在系统启动后,一次性通过OS(操作系统)获取较大的一块内存,并进行初始化;
分配单元202,用于利用内存分配API从所述内存块中分配内存,并向已分配的内存中添加控制信息,需要说明的是,上层应用通过专门的内存分配API从该内存块中进行内存申请。根据实际应用中对内存的使用情况,可以将内存分配API分为四类:普通的内存申请、用于关键资源的内存分配、提供额外functionbacktrace(可用于debug)的内存分配和从特定的内存池进行内存申请。每次调用完内存分配API后,用户需要自行判断内存指针是否为NULL:若不为NULL,则内存分配成功;若为NULL,则失败,用户需做相应的逻辑处理。但若是用于关键资源的内存分配失败,系统则会重启,这是和普通类型内存分配最显著的区别,内存分配失败可能是由于系统负载过重导致内存不够用,只有在必要的时候才能进行系统重启;提供额外functionbacktrace的内存分配:这种类型的内存分配可以设置追踪函数调用堆栈的级别,最多可以打印出7级函数,因此有利于理解整个函数调用过程,也便于后期的测试和debug;从特定的内存池进行内存申请,例如内存池为写保护模式(可用于后期测试过程中内存溢出的检测),在申请内存的时候,设置内存写保护(每页内的内存具有相同读写属性),若向具有只读属性的内存写数据,则会触发Segv。内存分配后,用户应该自行去判断内存分配是否真的生效,即判断返回地址是否为NULL。因为对于内存管理器而言,每次分配都会返还一个合法有效地址或是NULL;对于关键类型的分配则不用进行检测,因为分配若失败,内存管理器不会返回任何值,进程直接重启;
检测单元203,用于利用audit检测线程每隔预设时间对已分配的内存进行检测,如果超时之后仍未释放则产生内存告警,需要说明的是,在每个内存块中添加了控制信息,以此来判断是否发生内存泄漏、内存溢出以及数据被写坏,进一步的还可以判断具体是overflow还是underflow。这种audit检测线程可以每间隔五分钟检测一次,防止memory overflow/underflow和memory leak的产生,进而提高系统性能;
释放单元204,用于利用内存释放API释放使用完的内存,需要说明的是,用户在使用完内存后,通过专门的内存释放API进行释放,则释放的内存会重新加入可用内存链表中。
本申请实施例提供的第二种内存分配调度的装置,是在上述第一种内存分配调度的装置的基础上,还包括如下技术特征:
所述分配单元包括:
计算部件,用于计算所需内存的大小;
第一设置部件,用于设置functionbacktrace的级别,最多可以打印7级;
第二设置部件,用于设置内存的使用时间,可以以5分钟为间隔,取值范围为[1,255];
检索部件,用于检索内存链表,返回内存地址,而如果内存分配失败,若是普通内存申请,用户做相应的逻辑处理,会产生相应的log,若是用于关键资源的内存申请失败,系统直接重启。
需要说明的是,考虑到API的通用性,以及后期的代码维护,负责内存分配API需要至少以下3种信息:用于保存内存指针的地址,分配成功则指向被分配的内存地址,分配失败则被置为NULL;申请内存的大小;内存使用类型,如内存使用时间(以5分钟为单位)或无时间限制(用enumMEM_USE来定义)。如有需要还可以设置打印函数调用堆栈的级别,以及内存读写属性。
本申请实施例提供的第三种内存分配调度的装置,是在上述第二种内存分配调度的装置的基础上,还包括如下技术特征:
所述检索部件具体用于如果所述内存链表中包含用户所需大小的内存,则直接返回内存地址;否则将内存进行拆分出用户所需大小的内存,并将剩余的内存插入所述内存链表中。
本申请实施例提供的第四种内存分配调度的装置,是在上述第一种至第三种内存分配调度的装置中任一种的基础上,还包括如下技术特征:
清零单元,用于将分配的内存清零。
需要说明的是,这只是在特定情况下的一个可选项,如果要往分配的内存写数据,则可以不这样做,因为会浪费CPU时间。
本申请实施例提供的第五种内存分配调度的装置,是在上述第四种内存分配调度的装置的基础上,还包括如下技术特征:
拷贝单元,用于利用API将数据从其他地址拷贝到已分配的内存中。
需要说明的是,分配完内存之后,用户一般自己往内存里写数据。但如果数据是固定的,则直接可以利用API来完成内存分配和数据拷贝两个步骤,而无需用户进行拷贝。
综上所述,本申请实施例提供的上述方法和装置,可以显著提高系统内存的使用效率,同时在日常的产品开发与测试过程中,可以用来检测代码质量,提升开发的进度,保证产品的质量,在测试中可以通过打开相应的测试选项,来发现memory overflow/underflow,显著降低产品中与内存相关的bug率。
对所公开的实施例的上述说明,使本领域专业技术人员能够实现或使用本发明。对这些实施例的多种修改对本领域的专业技术人员来说将是显而易见的,本文中所定义的一般原理可以在不脱离本发明的精神或范围的情况下,在其它实施例中实现。因此,本发明将不会被限制于本文所示的这些实施例,而是要符合与本文所公开的原理和新颖特点相一致的最宽的范围。