G06F9/50
1.一种内存统计方法,其特征在于,包括:
在内存申请接口或内存释放接口被调用时,获取调用所述内存申请接口或所述内存释放接口的功能模块,并获取调用所述内存申请接口申请的内存大小,或获取调用所述内存释放接口释放的内存大小;
根据所述申请的内存大小或所述释放的内存大小,更新所述功能模块对应的内存记录中的占用内存总值。
2.如权利要求1所述的方法,其特征在于,在内存申请接口或内存释放接口被调用时,获取调用所述内存申请接口或所述内存释放接口的功能模块,包括:
在内存申请接口或内存释放接口被调用时,获取目标数据;所述目标数据包括调用所述内存申请接口或所述内存释放接口的调用函数,以及所述调用函数对应的PC寄存器中存储的函数代码段地址;
根据所述函数代码段地址计算所述调用函数所属的功能模块;所述调用函数所属的功能模块为调用所述内存申请接口或所述内存释放接口的功能模块。
3.如权利要求2所述的方法,其特征在于,所述目标数据还包括所述调用函数对应的FP寄存器的值;
根据所述函数代码段地址计算所述调用函数所属的功能模块,包括:
若根据所述函数代码段地址计算得到的计算结果为空,则根据所述FP寄存器的值,以计算出新的所述函数代码段地址;
根据新的所述函数代码段地址计算所述调用函数所属的功能模块。
4.如权利要求3所述的方法,其特征在于,所述方法还包括:
若根据新的所述函数代码段地址计算得到的计算结果仍为空,则在所述FP寄存器中向上取值,根据所述取值计算出新的所述函数代码段地址,并根据新的所述函数代码段地址计算所述调用函数所属的功能模块;
重复上述过程,直至根据所述函数代码段地址计算得到的计算结果非空,或重复次数达到次数阈值;
若重复次数达到所述次数阈值,则确定所述申请的内存大小或所述释放的内存大小为内核对应的内存大小。
5.如权利要求2-4任一项所述的方法,其特征在于,根据所述申请的内存大小或所述释放的内存大小,更新所述功能模块对应的内存记录中的占用内存总值,包括:
判断所述功能模块对应的内存记录中是否存在所述调用函数;
若不存在,在所述内存记录中关联记录所述调用函数与所述申请的内存大小或所述释放的内存大小;
若存在,根据所述申请的内存大小或所述释放的内存大小,更新所述内存记录中所述调用函数对应的占用内存总值。
6.如权利要求5所述的方法,其特征在于,所述目标数据还包括所述调用函数中调用所述内存申请接口或所述内存释放接口的函数行的行号;
在所述内存记录中关联记录所述调用函数与所述申请的内存大小或所述释放的内存大小,包括:
在所述内存记录中关联记录所述调用函数、所述行号、各所述行号对应的函数行调用所述内存申请接口所申请的内存大小或调用所述内存释放接口所释放的内存大小;
对应的,根据所述申请的内存大小或所述释放的内存大小,更新所述内存记录中所述调用函数对应的占用内存总值,包括:
根据各所述行号对应的函数行调用所述内存申请接口所申请的内存大小或调用所述内存释放接口所释放的内存大小,分别更新各所述行号对应的占用内存总值。
7.如权利要求2-4任一项所述的方法,其特征在于,所述方法还包括:重定向所述内存申请接口或内存释放接口中的调用函数指针;
在内存申请接口或内存释放接口被调用时,获取目标数据,包括:
在内存申请接口或内存释放接口被调用时,通过重定向后的所述调用函数指针获取所述目标数据。
8.一种内存统计装置,其特征在于,包括:
获取模块,用于在内存申请接口或内存释放接口被调用时,获取调用所述内存申请接口或所述内存释放接口的功能模块,并获取调用所述内存申请接口申请的内存大小,或获取调用所述内存释放接口释放的内存大小;
处理模块,根据所述申请的内存大小或所述释放的内存大小,更新所述功能模块对应的内存记录中的占用内存总值。
9.一种电子设备,其特征在于,包括处理器和存储器;所述处理器用于执行所述存储器中存储的一个或者多个指令,以实现如权利要求1-7任一项所述的方法。
10.一种计算机可读存储介质,其特征在于,所述计算机可读存储介质存储有一个或者多个程序,所述一个或者多个程序可被一个或者多个处理器执行,以实现如权利要求1-7任一项所述的方法。
本申请涉及计算机技术领域,具体而言,涉及一种内存统计方法、装置、电子设备及计算机可读存储介质。
内存是系统中的重要部件,伴随技术的不断革新,系统功能的不断丰富,内存的合理分配使用显得尤为重要。在系统中经常会出现各种内存问题,常见的内存问题主要有以下两种:
第一种:在系统开发过程中,由于软件设计不合理,导致某些功能模块占用太多内存,从而降低了系统整体的性能。例如:某一功能模块没有设置其所占内存的上限值,程序在运行的过程中不停的分配内存,直到结束的时候才释放内存。对于一个功能模块而言,运行时长可能长达几天、几周甚至几个月,由于没有设置上限值,不及时的释放内存,可能导致最终耗尽系统的所有内存,导致系统无法使用。
第二种:在系统开发过程中,由于对内存的使用不规范,没有对已分配的内存进行释放,导致出现了内存泄露的问题。当出现内存泄漏时,会使系统中可用内存越来越少,最终导致系统崩溃,无法正常使用。
为解决上述问题,需要对内存使用情况进行统计,以便及时发现问题并及时进行处理。而目前常见的内存分析工具,例如kmemleak、kasan等,由于功能过于庞大,依赖太多,导致这些工具本身就需要占用很多的系统资源,并不适合在资源紧张的系统(例如嵌入式系统)中使用,而且这些工具是从系统整体上进行分析的,这些工具并不能统计各个功能模块占用的内存,因此也难以解决上述问题。
本申请实施例的目的在于提供一种内存统计方法、装置、电子设备及计算机可读存储介质,用以解决上述问题。
本申请实施例提供了一种内存统计方法,包括:在内存申请接口或内存释放接口被调用时,获取调用所述内存申请接口或所述内存释放接口的功能模块,并获取调用所述内存申请接口申请的内存大小,或获取调用所述内存释放接口释放的内存大小;根据所述申请的内存大小或所述释放的内存大小,更新所述功能模块对应的内存记录中的占用内存总值。
通过上述实现过程,通过在内存申请接口或内存释放接口被调用时,获取调用该内存申请接口或调用该内存释放接口的功能模块,并获取调用该内存申请接口申请的内存大小,或获取调用该内存释放接口释放的内存大小,从而对功能模块对应的内存记录中的占用内存总值进行更新。这样,在功能模块每一次申请内存或释放内存时,都会对功能模块对应的占用内存总值进行更新,从而可以不断更新出功能模块对内存的最新的占用量,实现对各功能模块所占内存的实时监测,从而在系统出现内存问题时,根据各功能模块对应的内存记录,就可以快速定位出存在问题的功能模块,从而及时进行处理,解决了现有内存分析工具无法定位问题功能模块的问题。且上述实现方式在程序实现上并不复杂,无需占用大量资源,从而解决了利用现有内存分析工具需要占用很多的系统资源,并不适合在资源紧张的系统(例如嵌入式系统)中使用的问题。
进一步地,在内存申请接口或内存释放接口被调用时,获取调用所述内存申请接口或所述内存释放接口的功能模块,包括:在内存申请接口或内存释放接口被调用时,获取目标数据;所述目标数据包括调用所述内存申请接口或所述内存释放接口的调用函数,以及所述调用函数对应的PC(Program Counter,程序计数器)寄存器中存储的函数代码段地址;根据所述函数代码段地址计算所述调用函数所属的功能模块;所述调用函数所属的功能模块为调用所述内存申请接口或所述内存释放接口的功能模块。
在上述实现方式中,通过调用内存申请接口或所述内存释放接口的调用函数,以及调用函数对应的PC寄存器中存储的函数代码段地址,即可确定出调用函数所属的功能模块,实现对于调用内存申请接口或内存释放接口的功能模块的准确确定。
进一步地,所述目标数据还包括所述调用函数对应的FP寄存器的值;根据所述函数代码段地址计算所述调用函数所属的功能模块,包括:若根据所述函数代码段地址计算得到的计算结果为空,则根据所述FP寄存器的值,以计算出新的所述函数代码段地址;根据新的所述函数代码段地址计算所述调用函数所属的功能模块。
在系统中,可能存在复杂的调用关系,从而可能出现对PC寄存器中存储的调用函数的函数代码段地址进行计算时,计算结果为空的情况。而在上述实现方式中,在对PC寄存器中存储的调用函数的函数代码段地址进行计算时,若计算结果为空,即可根据FP寄存器的值重新计算出新的调用函数的函数代码段地址,以向上溯源,尝试追溯出调用函数所属的功能模块。
进一步地,所述方法还包括:若根据新的所述函数代码段地址计算得到的计算结果仍为空,则在所述FP寄存器中向上取值,根据所述取值计算出新的所述函数代码段地址,并根据新的所述函数代码段地址计算所述调用函数所属的功能模块;重复上述过程,直至根据所述函数代码段地址计算得到的计算结果非空,或重复次数达到次数阈值;若重复次数达到所述次数阈值,则确定所述申请的内存大小或所述释放的内存大小为内核对应的内存大小。
在上述实现过程中,通过设置次数阈值,在重复次数达到次数阈值后,即不再向上溯源,而是将申请的内存大小或释放的内存大小归于内核,这就可以避免因对过于复杂的调用关系进行溯源从而造成大量的系统开销,影响系统性能。
进一步地,根据所述申请的内存大小或所述释放的内存大小,更新所述功能模块对应的内存记录中的占用内存总值,包括:判断所述功能模块对应的内存记录中是否存在所述调用函数;若不存在,在所述内存记录中关联记录所述调用函数与所述申请的内存大小或所述释放的内存大小;若存在,根据所述申请的内存大小或所述释放的内存大小,更新所述内存记录中所述调用函数对应的占用内存总值。
在上述实现过程中,将调用函数进行记录,并记录各调用函数对应的占用内存总值,从而在功能模块并确定出问题时,可以根据各调用函数对应的占用内存总值,实现对于出现问题的调用函数的定位,从而便于进行问题处理。
进一步地,所述目标数据还包括所述调用函数中调用所述内存申请接口或所述内存释放接口的函数行的行号;
在所述内存记录中关联记录所述调用函数与所述申请的内存大小或所述释放的内存大小,包括:在所述内存记录中关联记录所述调用函数、所述行号、各所述行号对应的函数行调用所述内存申请接口所申请的内存大小或调用所述内存释放接口所释放的内存大小;
对应的,根据所述申请的内存大小或所述释放的内存大小,更新所述内存记录中所述调用函数对应的占用内存总值,包括:根据各所述行号对应的函数行调用所述内存申请接口所申请的内存大小或调用所述内存释放接口所释放的内存大小,分别更新各所述行号对应的占用内存总值。
在上述实现过程中,通过关联记录各行号对应的占用内存总值,从而在定位出问题功能模块中,出现问题的调用函数时,可以进一步的根据各行号对应的占用内存总值,实现对于可能出现问题的函数行的定位,从而更便于进行问题处理。
进一步地,所述方法还包括:重定向所述内存申请接口或内存释放接口中的调用函数指针;在内存申请接口或内存释放接口被调用时,获取目标数据,包括:在内存申请接口或内存释放接口被调用时,通过重定向后的所述调用函数指针获取所述目标数据。
在上述实现过程中,通过重定向的方式,可以很容易地实现与内存申请接口或内存释放接口的调用相关的目标数据的获取,从而无需设计复杂的数据获取逻辑,可以减小对系统的资源占用。
本申请实施例还提供了一种内存统计装置,包括:获取模块,用于在内存申请接口或内存释放接口被调用时,获取调用所述内存申请接口或所述内存释放接口的功能模块,并获取调用所述内存申请接口申请的内存大小,或获取调用所述内存释放接口释放的内存大小;处理模块,根据所述申请的内存大小或所述释放的内存大小,更新所述功能模块对应的内存记录中的占用内存总值。
本申请实施例还提供了一种电子设备,包括处理器和存储器;所述处理器用于执行所述存储器中存储的一个或者多个指令,以实现上述任一种的方法。
本申请实施例中还提供了一种计算机可读存储介质,所述计算机可读存储介质存储有一个或者多个程序,所述一个或者多个程序可被一个或者多个处理器执行,以实现上述任一种的方法。
为了更清楚地说明本申请实施例的技术方案,下面将对本申请实施例中所需要使用的附图作简单地介绍,应当理解,以下附图仅示出了本申请的某些实施例,因此不应被看作是对范围的限定,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他相关的附图。
图1为本申请实施例提供的一种内存统计方法的流程示意图;
图2为本申请实施例提供的一种调用内存申请接口或内存释放接口的功能模块的获取流程示意图;
图3为本申请实施例提供的第一种数据关联统计方式的示意图;
图4为本申请实施例提供的第二种数据关联统计方式的示意图;
图5为本申请实施例提供的第三种数据关联统计方式的示意图;
图6为本申请实施例提供的一种内存统计装置的结构示意图;
图7为本申请实施例提供的一种电子设备的结构示意图。
下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行描述。
为了解决目前常见的内存分析工具功能过于庞大,依赖太多,导致这些工具本身就需要占用很多的系统资源,并不适合在资源紧张的系统(例如嵌入式系统)中使用,而且这些工具是从系统整体上进行分析的,这些工具并不能统计各个功能模块占用的内存,无法实现功能模块级的内存统计,从而无法进行引发内存问题的功能模块的定位的情况,本申请实施例中提供了一种内存统计方法,可参见图1所示,该内存统计方法包括:
S101:在内存申请接口或内存释放接口被调用时,获取调用该内存申请接口或该内存释放接口的功能模块,并获取调用该内存申请接口申请的内存大小,或获取调用该内存释放接口释放的内存大小。
可以理解,在系统中会提供用于进行内存申请或内存释放的接口。本申请实施例中将用于进行内存申请的接口称之为内存申请接口,用于进行内存释放的接口称之为内存释放接口。
在一些实施例中,内存申请接口和内存释放接口可以对应同一接口函数,通过调用该接口函数,实现内存申请操作,或实现内存释放操作。而在另一些实施例中,内存申请接口和内存释放接口也可以对应不同的接口函数,从而在需要进行内存申请时,调用内存申请接口对应的接口函数,在需要进行内存释放时,调用内存释放接口对应的接口函数。
考虑到在系统中,功能模块通常是通过一些接口函数对内存申请接口或内存释放接口进行调用(为便于描述,本申请实施例中称调用内存申请接口或内存释放接口的接口函数为调用函数),因此在内存申请接口或内存释放接口被调用时,通常只能获取到调用函数的相关信息,并不能直接获取到调用内存申请接口或内存释放接口的功能模块的信息。因此,为了获取调用所述内存申请接口或所述内存释放接口的功能模块,在本申请实施例中,可以通过图2所示的方式进行获取:
S201:在内存申请接口或内存释放接口被调用时,获取目标数据。
在本申请实施例中,目标数据可以包括调用内存申请接口或内存释放接口的调用函数,以及调用函数对应的PC寄存器中存储的函数代码段地址。在本申请实施例中,可以采用系统提供的FUNCTION宏功能获取调用函数,并可以采用系统提供的current_text_addr()函数获取PC寄存器中存储的函数代码段地址。
S202:根据PC寄存器中存储的函数代码段地址计算调用函数所属的功能模块。
在本申请实施例中,可以通过module_text_address()函数对PC寄存器中存储的函数代码段进行计算,以得到调用函数所属的功能模块。其中,()内为函数的参数,执行步骤S202时,括号内的参数为PC寄存器中存储的函数代码段地址。
应理解,调用函数所属的功能模块即为调用内存申请接口或内存释放接口的功能模块。这样,就实现了对于调用内存申请接口或内存释放接口的功能模块的快速确定。
需要注意的是,在实际应用中,在调用内存申请接口或内存释放接口时,可能存在复杂的调用关系,从而可能会出现对PC寄存器中存储的调用函数的函数代码段地址进行计算时,计算结果为空的情况。为尽可能得到调用函数所属的功能模块,在获取到的目标数据中,还可以包括调用函数对应的FP寄存器的值。其中,调用函数对应的FP寄存器的值可以但不限于通过内建函数builtin_frame_address(0)获取得到。
此时,若根据PC寄存器中存储的函数代码段地址计算得到的计算结果为空,则可以根据FP寄存器的值,计算出新的函数代码段地址,然后根据新的函数代码段地址重新计算调用函数所属的功能模块。
此时,若根据新的函数代码段地址计算得到的计算结果仍为空,则可以在FP寄存器中向上取值,根据该FP寄存器的取值计算出新的函数代码段地址,并根据新的函数代码段地址计算调用函数所属的功能模块。
在一实施方式中,可以重复上述过程,直至根据函数代码段地址计算得到的计算结果非空。
应理解,FP寄存器中是以依次堆叠的方式依次记录有调用函数被调用时的各调用关系的数据。因此,在FP寄存器中从下往上依次取值进行函数代码段地址的重新计算,即可实现对于调用函数的调用关系的逐级向上溯源,从而可以溯源得到调用该调用函数的功能模块。
而考虑到过于复杂的调用关系可能会造成需要大量时间和资源用于进行溯源,为此在另一实施方式中,同样可以重复上述过程,但是截止条件除了可以包括根据函数代码段地址计算得到的计算结果非空外,还可以包括重复次数达到次数阈值。也即,可以重复上述过程,直至根据函数代码段地址计算得到的计算结果非空,或重复次数达到次数阈值。
而若是因为重复次数达到次数阈值而截止的,则可以确定所申请的内存大小或所释放的内存大小为内核对应的内存大小,也即可以将所申请的内存大小或所释放的内存大小归于内核,以避免因对过于复杂的调用关系进行溯源从而造成大量的系统开销,影响系统性能。
其中,次数阈值可以由工程师根据系统实际情况进行设置,例如可以设置为5,但不作为限制。
S102:根据申请的内存大小或释放的内存大小,更新该功能模块对应的内存记录中的占用内存总值。
在本申请实施例的一种可选实施方式中,可以按照如图3所示的方式,仅关联记录各功能模块,以及各功能模块对应的占用内存总值。
可以理解,在本可选实施方式中,可以先判断是否存在该功能模块对应的内存记录。若不存在,则可以创建一空白记录,并在该空白记录中填入该功能模块的标识信息(例如功能模块的名称)和步骤S101中获取到的申请的内存大小或释放的内存大小,此时申请的内存大小或释放的内存大小即为该功能模块对应的占用内存总值。若存在,则可以根据申请的内存大小或释放的内存大小,更新该功能模块对应的内存记录中的占用内存总值。更新时,若是申请的内存大小,则在原占用内存总值基础上加上该申请的内存大小,若是释放的内存大小,则在原占用内存总值基础上减去该申请的内存大小。
在本申请实施例的另一种可选实施方式中,也可以按照如图4所示的方式,关联记录各功能模块,各功能模块所调用的调用函数,以及各调用函数对应的占用内存总值。这样,各功能模块的所有调用函数对应的占用内存总值之和,即为各功能模块的占用内存总值。
在上述可选实施方式中,在进行功能模块对应的占用内存总值的更新时,可以先判断是否存在该功能模块对应的内存记录。
若不存在,则可以创建一空白记录,并在该空白记录中填入该功能模块的标识信息(例如功能模块的名称)、本次获取到的调用函数的标识信息(例如调用函数的名称)、调用函数所申请的内存大小或释放的内存大小,此时申请的内存大小或释放的内存大小即为该功能模块对应的占用内存总值。
若存在,则可以先判断该功能模块对应的内存记录中是否存在该调用函数。若不存在该调用函数,则在该内存记录中关联记录该调用函数与所申请的内存大小或所释放的内存大小。若存在该调用函数,则根据申请的内存大小或释放的内存大小,更新该内存记录中调用函数对应的占用内存总值。更新时,若是申请的内存大小,则在调用函数对应的占用内存总值的基础上加上该申请的内存大小,若是释放的内存大小,则在调用函数对应的占用内存总值的基础上减去该释放的内存大小。
这样,通过图4所示的表格,在功能模块并确定出问题时,可以根据各调用函数对应的占用内存总值,实现对于出现问题的调用函数的定位,从而可以直接对该出现问题的调用函数进行分析与调整,以快速消除内存问题。
在本申请实施例的另一种可选实施方式中,也可以按照如图5所示的方式,关联记录各功能模块,各功能模块所调用的调用函数,调用函数调用内存申请接口或内存释放接口时所采用的函数行的行号,以及各行号对应的占用内存总值。这样,各功能模块的所有调用函数的行号对应的占用内存总值之和,即为各功能模块的占用内存总值。
在上述可选实施方式中,在获取目标数据时,可以将调用函数调用内存申请接口或内存释放接口时所采用的函数行的行号作为目标数据的一部分,一并进行获取。示例性的,可以通过LINE宏获取调用函数调用内存申请接口或内存释放接口时所采用的函数行的行号,但不作为限制。
在上述可选实施方式中,在进行功能模块对应的占用内存总值的更新时,可以先判断是否存在该功能模块对应的内存记录。
若不存在,则可以创建一空白记录,并在该空白记录中填入该功能模块的标识信息(例如功能模块的名称)、本次获取到的调用函数的标识信息(例如调用函数的名称)、调用函数调用内存申请接口或内存释放接口时所采用的函数行的行号、各函数行所申请的内存大小或释放的内存大小。此时各函数行所申请的内存大小或所释放的内存大小即为该功能模块对应的占用内存总值。
若存在,则可以先判断该功能模块对应的内存记录中是否存在该调用函数。若不存在该调用函数,则在该内存记录中关联记录该调用函数、该调用函数对应获取到的行号、以及各行号对应的申请的内存大小或释放的内存大小。
若存在该调用函数,则再判断该内存记录中,该调用函数是否关联记录有各行号。
对任一行号而言,若该行号未记录,则在该内存记录中将该行号与该调用函数关联记录,并关联记录该行号对应的申请的内存大小或释放的内存大小。若该行号已记录,则根据该行号对应的申请的内存大小或释放的内存大小,更新该行号对应的占用内存总值。更新时,若是申请的内存大小,则在该行号对应的占用内存总值的基础上加上该申请的内存大小,若是释放的内存大小,则在该行号对应的占用内存总值的基础上减去该释放的内存大小。
这样,通过图5所示的表格,在功能模块并确定出问题时,可以根据各调用函数对应的占用内存总值(同一调用函数的各行号对应的占用内存总值之和),实现对于出现问题的调用函数的定位,然后进一步的基于该调用函数的各行号对应的占用内存总值,可以实现对于可能出现问题的函数行的定位,从而可以直接对该出现问题的调用函数的函数行进行上下文分析与调整,以快速消除内存问题。
在本申请实施例中,在进行关联记录时,可以采用但不限于哈希桶、哈希链表的方式进行记录。例如,可以以功能模块的名称作为关键字,采用hash桶结构进行整理,将调用函数的函数名称、行号、以及行号对应的占用内存总值以结构体的形式,统计到所属模块的hash链表中。
在本申请实施例中,可以通过重定向内存申请接口或内存释放接口中的调用函数指针的方式,实现对于目标数据的获取。
示例性的,可以预先设置一个用于实现上述内存统计方法的功能模块,并将内存申请接口和内存释放接口中的调用函数指针,赋值为该功能模块的地址。这样,在内存申请接口或内存释放接口被调用时,通过重定向后的调用函数指针,目标数据即可被传输至该功能模块中,从而执行上述内存统计方法。这样,通过重定向的方式,可以很容易地实现与内存申请接口或内存释放接口的调用相关的目标数据的获取,从而无需设计复杂的数据获取逻辑,可以减小对系统的资源占用。
在本申请实施例中,对于保存的内存记录,可以采用堆排序的方式,进行从大到小排序,并可以提供显示服务功能,以将排序后的各功能模块的内存占用情况显示给用户。例如,可以通过meminfo命令实现对于排序后的各功能模块的内存占用情况的显示。meminfo命令用于显示当前系统中各功能模块占用内存情况(包含功能模块的模块名称以及功能模块的占用内存总值),可以通过使用meminfo命令,实时的查看各功能模块的占用内存总值。
本申请实施例所提供的内存统计方法,通过在内存申请接口或内存释放接口被调用时,获取调用该内存申请接口或调用该内存释放接口的功能模块,并获取调用该内存申请接口申请的内存大小,或获取调用该内存释放接口释放的内存大小,从而对功能模块对应的内存记录中的占用内存总值进行更新。这样,在功能模块每一次申请内存或释放内存时,都会对功能模块对应的占用内存总值进行更新,从而可以不断更新出功能模块对内存的最新的占用量,实现对各功能模块所占内存的实时监测,从而在系统出现内存问题时,根据各功能模块对应的内存记录,就可以快速定位出存在问题的功能模块,从而及时进行处理,解决了现有内存分析工具无法定位问题功能模块的问题。且上述实现方式在程序实现上并不复杂,无需占用大量资源,从而解决了利用现有内存分析工具需要占用很多的系统资源,并不适合在资源紧张的系统(例如嵌入式系统)中使用的问题。
实施例二:
本实施例在实施例一的基础上,以一种具体的实现过程为例,为本申请做进一步示例说明。
在系统中,可以增加内核patch,将内存申请接口和内存释放接口重定向,例如将接口kmalloc重定向为tos_kmalloc。并且在重定向的接口中设置调用函数指针tos_kmalloc_hook。
新增模块memwatch.ko。在内核启动之后,首先加载该模块memwatch.ko,用于给tos_kmalloc_hook赋值,赋值为memwatch.ko的地址。
在加载memwatch.ko模块之后,开始对系统中各功能模块所占内存进行实时监测:
当功能模块在运行过程中,调用了内存申请接口或内存释放接口(即kmalloc),实际运行时会调用重定向的接口(tos_kmalloc),最终通过调用函数指针tos_kmalloc_hook,将数据传回memwatch.ko模块。
传回的数据包括:调用接口kmalloc的调用函数(使用FUNCTION宏获取)、调用函数调用接口kmalloc所使用的函数行的行号(使用LINE宏获取)、调用函数对应的PC寄存器中存储的函数代码段地址(使用current_text_addr()函数获取)和FP寄存器的值(使用内建函数builtin_frame_address(0)获取)、调用函数调用接口kmalloc所使用的各函数行对应申请或释放的内存大小(通过接口kmalloc获取)。
memwatch.ko模块使用函数module_text_address(函数代码段地址)计算PC寄存器中存储的函数代码段地址所属的功能模块,若计算结果不为空,则计算结果即为调用函数所属的功能模块,若计算结果为空,则根据FP寄存器的值,以计算出新的函数代码段地址,使用函数module_text_address(函数代码段地址)重新计算调用函数所属的功能模块。若计算结果仍为空,则在FP寄存器中向上取值,重新计算出新的函数代码段地址,并使用函数module_text_address(函数代码段地址)重新计算调用函数所属的功能模块。若连续5次使用函数module_text_address(函数代码段地址)进行计算得到的计算结果均为空,则确定本次申请或释放的内存大小为内核占用的内存,不用于进行功能模块的占用内存总值的更新。
memwatch.ko模块在确定出调用函数所属的功能模块之后,根据功能模块的模块名称到记录表中的该功能模块,并根据函数名到记录表中该功能模块对应的该调用函数,并到该调用函数对应的各行号,分别对各行号对应的占用内存总值进行更新。具体而言,对申请的内存大小进行加法运算,对于释放的内存大小进行减法运算。
在记录表中,以功能模块的模块名称作为关键字,采用hash桶结构进行整理,将调用函数的函数名称、以及调用接口kmalloc的函数行的行号用结构体的形式,统计到所属模块的hash链表中。
通过上述方案,可以不断更新出功能模块对内存的最新的占用量,实现对各功能模块所占内存的实时监测,可以快速定位出存在问题的功能模块,从而及时进行处理。且本申请的方案无需占用大量资源适合在资源紧张的系统(例如嵌入式系统)中使用。
实施例三:
基于同一发明构思,本申请实施例中还提供了一种内存统计装置600。请参阅图6所示,图6示出了采用图1所示的方法的内存统计装置。应理解,装置600具体的功能可以参见上文中的描述,为避免重复,此处适当省略详细描述。装置600包括至少一个能以软件或固件的形式存储于存储器中或固化在装置600的操作系统中的软件功能模块。具体地:
参见图6所示,装置600包括:获取模块601和处理模块602。其中:
获取模块601,用于在内存申请接口或内存释放接口被调用时,获取调用所述内存申请接口或所述内存释放接口的功能模块,并获取调用所述内存申请接口申请的内存大小,或获取调用所述内存释放接口释放的内存大小;
处理模块602,根据所述申请的内存大小或所述释放的内存大小,更新所述功能模块对应的内存记录中的占用内存总值。
在本申请实施例的一种可行实施方式中,所述获取模块601具体用于:
在内存申请接口或内存释放接口被调用时,获取目标数据;所述目标数据包括调用所述内存申请接口或所述内存释放接口的调用函数,以及所述调用函数对应的PC寄存器中存储的函数代码段地址;
根据所述函数代码段地址计算所述调用函数所属的功能模块;所述调用函数所属的功能模块为调用所述内存申请接口或所述内存释放接口的功能模块。
在本申请实施例中,所述目标数据还包括所述调用函数对应的FP寄存器的值;
所述获取模块601具体用于:
若根据所述函数代码段地址计算得到的计算结果为空,则根据所述FP寄存器的值,以计算出新的所述函数代码段地址;
根据新的所述函数代码段地址计算所述调用函数所属的功能模块。
在本申请实施例中,所述获取模块601具体还用于:若根据新的所述函数代码段地址计算得到的计算结果仍为空,则在所述FP寄存器中向上取值,根据所述取值计算出新的所述函数代码段地址,并根据新的所述函数代码段地址计算所述调用函数所属的功能模块;重复上述过程,直至根据所述函数代码段地址计算得到的计算结果非空,或重复次数达到次数阈值;
所述处理模块602还用于,若重复次数达到所述次数阈值,则确定所述申请的内存大小或所述释放的内存大小为内核对应的内存大小。
在本申请实施例中,所述处理模块602具体用于:
判断所述功能模块对应的内存记录中是否存在所述调用函数;
若不存在,在所述内存记录中关联记录所述调用函数与所述申请的内存大小或所述释放的内存大小;
若存在,根据所述申请的内存大小或所述释放的内存大小,更新所述内存记录中所述调用函数对应的占用内存总值。
在本申请实施例中,所述目标数据还包括所述调用函数中调用所述内存申请接口或所述内存释放接口的函数行的行号;所述处理模块602具体用于:
在所述内存记录中关联记录所述调用函数、所述行号、各所述行号对应的函数行调用所述内存申请接口所申请的内存大小或调用所述内存释放接口所释放的内存大小;
根据各所述行号对应的函数行调用所述内存申请接口所申请的内存大小或调用所述内存释放接口所释放的内存大小,分别更新各所述行号对应的占用内存总值。
在本申请实施例中,所述处理模块602还用于重定向所述内存申请接口或内存释放接口中的调用函数指针;所述获取模块601具体用于,在内存申请接口或内存释放接口被调用时,通过重定向后的所述调用函数指针获取所述目标数据。
需要理解的是,出于描述简洁的考量,部分实施例一中描述过的内容在本实施例中不再赘述。
实施例四:
本实施例提供了一种电子设备,参见图7所示,其包括处理器701和存储器702。其中:
处理器701用于执行存储器702中存储的一个或多个指令,以实现上述实施例一和/或实施例二中的内存统计方法。
可以理解,图7所示的结构仅为示意,电子设备还可包括比图7中所示更多或者更少的组件,或者具有与图7所示不同的配置。
例如,电子设备还可以具有通信总线,以通过通信总线实现处理器701和存储器702之间的通信连接。或者,电子设备还可以具有外部通信接口,例如USB接口等,以实现数据的转存。此外,电子设备还可以具有显示屏等信息展示组件,以进行信息的显示。此外,电子设备还可以具有键盘等信息输入组件,以进行信息的输入。
可选的,该电子设备可以是诸如电脑、平板、服务器等具有数据处理能力,且可以安装版图设计软件的设备,但不作为限制。
本实施例还提供了一种计算机可读存储介质,如软盘、光盘、硬盘、闪存、U盘、SD(Secure Digital Memory Card,安全数码卡)卡、MMC(Multimedia Card,多媒体卡)卡等,在该计算机可读存储介质中存储有实现上述各个步骤的一个或者多个程序,这一个或者多个程序可被一个或者多个处理器执行,以实现上述实施例一和/或实施例二中的内存统计方法。在此不再赘述。
在本申请所提供的实施例中,应该理解到,所揭露装置和方法,可以通过其它的方式实现。以上所描述的装置实施例仅仅是示意性的,例如,所述单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,又例如,多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些通信接口,装置或单元的间接耦合或通信连接,可以是电性,机械或其它的形式。
另外,作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。
再者,在本申请各个实施例中的各功能模块可以集成在一起形成一个独立的部分,也可以是各个模块单独存在,也可以两个或两个以上模块集成形成一个独立的部分。
在本文中,诸如第一和第二等之类的关系术语仅仅用来将一个实体或者操作与另一个实体或操作区分开来,而不一定要求或者暗示这些实体或操作之间存在任何这种实际的关系或者顺序。
在本文中,多个是指两个或两个以上。
以上所述仅为本申请的实施例而已,并不用于限制本申请的保护范围,对于本领域的技术人员来说,本申请可以有各种更改和变化。凡在本申请的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本申请的保护范围之内。
本文发布于:2023-04-13 09:48:02,感谢您对本站的认可!
本文链接:https://patent.en369.cn/patent/3/85946.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |