发明内容
本发明了提供了一种统计应用程序中的函数调用的方法及组件,以解决目前面临的如果软件已经发布,则没有办法来统计每个函数的调用时间和调用次数的技术问题。
为解决上述技术问题,本发明提供了一种统计应用程序中的函数调用的方法,所述方法应用在统计应用程序中的函数调用的组件中,所述方法包括:
在所述应用程序运行时,利用所述组件中的钩子函数库监控统计调用信息文件MAP文件中的所有函数的函数头在预设时间内各自的调用次数,和所述所有函数的函数头各自的调用时刻;其中,所述组件注入所述应用程序的进程中;
利用所述钩子函数库监控统计所述MAP文件中的所有函数的函数尾各自的调用时刻;
基于所述MAP文件中的所述所有函数的函数头各自的调用时刻以及所述所有函数的函数尾各自的调用时刻,确定出所述所有函数在所述预设时间内的调用时间。
为了避免发布之后的应用程序无法监控其函数调用情况(调用时间、调用次数等等),本发明通过上述方法在应用程序运行时对其进行监控,然后将该组件注入到运行的应用程序进程中,该组件具有监控应用程序的所有函数调用情况的功能,并统计每个函数的调用次数和调用时间,最后将统计的结果输出。
优选的,所述MAP文件中至少记录了所述所有函数的函数名称、函数地址,函数长度、所有的全局变量、全局变量名的地址。有了MAP文件,本发明就可以直接调用MAP文件,进而为对所有函数进行监控。
优选的,所述利用所述组件中的钩子函数库钩子函数库监控统计调用信息文件MAP文件中的所有函数的函数头在预设时间内各自的调用次数,和所述所有函数的函数头各自的调用时刻之前,还包括:利用所述钩子函数库的钩子函数监控所述所有函数的函数头。钩子函数库可以将自身的代码“融入”被监控的程序的进程中,成为目标进程的一个部分,从而可以对程序进行监控,还可以在目标代码中加入自己的逻辑。
优选的,所述利用所述钩子函数库的钩子函数监控所述所有函数的函数头,包括:获取所述组件在终端设备的内存中的起始地址;读取所述MAP文件中的所有函数的函数名称、函数地址;其中,所述所有函数的函数地址为各自相对于所述组件的函数地址;将所述所有函数的函数地址各自相对于所述组件的函数地址分别和所述组件在内存中的起始地址求和,获得所述所有函数各自的内存地址;所述所有函数各自的内存地址就是所述所有函数各自的函数头;利用所述钩子函数库对所述所有函数各自的内存地址进行监控。
优选的,所述将所述所有函数的函数地址各自相对于所述组件的函数地址分别和所述组件在内存中的起始地址求和,获得所述所有函数各自的内存地址;所述所有函数各自的内存地址就是所述所有函数各自的函数头,包括:利用所述钩子函数库监控所述所有函数从各自的内存地址调用的调用次数和调用时刻。
优选的,所述利用所述钩子函数库监控统计所述MAP文件中的所有函数的函数尾各自的调用时刻,包括:读取所述所有函数的函数名称、函数地址、函数长度;将所述所有函数各自的函数地址和函数长度求和,获得所述所有函数各自的尾地址;利用所述钩子函数库对所述所有函数各自的尾地址进行监控,获得所述所有函数各自的尾地址的调用时刻。
本发明公开了一种统计应用程序中的函数调用的组件,所述组件注入在所述应用程序的进程中,用以对所述应用程序中的所有函数的调用时间和调用次数进行监控,包括:
第一监控模块,用于在所述应用程序运行时,利用所述组件中的钩子函数库监控统计调用信息文件MAP文件中的所有函数的函数头在预设时间内各自的调用次数,和所述所有函数的函数头各自的调用时刻;其中,所述组件注入所述应用程序的进程中;
第二监控模块,用于利用所述钩子函数库监控统计所述MAP文件中的所有函数的函数尾各自的调用时刻;
确定模块,用于基于所述MAP文件中的所述所有函数的函数头各自的调用时刻以及所述所有函数的函数尾各自的调用时刻,确定出所述所有函数在所述预设时间内的调用时间。
优选的,所述MAP文件中至少记录了所述所有函数的函数名称、函数地址,函数长度、所有的全局变量、全局变量名的地址。
优选的,所述组件还包括:
第三监控模块,用于利用所述钩子函数库的钩子函数监控所述所有函数的函数头。
优选的,所述第三监控模块,包括:
获取模块,用于获取所述组件在终端设备的内存中的起始地址;
读取模块,用于读取所述MAP文件中的所有函数的函数名称、函数地址;其中,所述所有函数的函数地址为各自相对于所述组件的函数地址;
获得模块,用于将所述所有函数的函数地址各自相对于所述组件的函数地址分别和所述组件在内存中的起始地址求和,获得所述所有函数各自的内存地址;所述所有函数各自的内存地址就是所述所有函数各自的函数头;
监控子模块,用于利用所述钩子函数库对所述所有函数各自的内存地址进行监控。
通过本发明的一个或者多个技术方案,本发明具有以下有益效果或者优点:
本发明公开了一种统计应用程序中的函数调用的方法,为了避免发布之后的应用程序无法监控其函数调用情况,所述方法应用在统计应用程序中的函数调用的组件中,用以监控应用程序的函数调用情况。在该应用程序运行时,利用所述组件中的钩子函数库监控统计调用信息文件MAP文件中的所有函数的函数头在预设时间内各自的调用次数,和所有函数的函数头各自的调用时刻;然后利用所述钩子函数库监控统计所述MAP文件中的所有函数的函数尾各自的调用时刻;基于所述MAP文件中的所述所有函数的函数头各自的调用时刻以及所述所有函数的函数尾各自的调用时刻,确定出所述所有函数在所述预设时间内的调用时间。进而,本发明可以在应用程序运行时,实时统计函数的调用情况。
具体实施方式
本发明了提供了一种统计应用程序中的函数调用的方法及组件,为了避免发布之后的应用程序无法监控其函数调用情况(调用时间、调用次数等等),本发明编写了一个可以用于在应用程序运行时对其进行监控的组件,然后将该组件注入到运行的应用程序进程中,该组件具有监控应用程序的所有函数调用情况的功能,并统计每个函数的调用次数和调用时间,最后将统计的结果输出。所以后续的HOOK(钩子函数,用来监控函数的调用情况)功能代码都编写在这个组件中。组件注入的方式则有很多,可以是远程线程注入、消息钩子注入等等。
本发明的应用程序可为任意应用程序,例如直播视频软件、语音聊天软件等等,对此本发明不做限制。
为了使本申请所属技术领域中的技术人员更清楚地理解本申请,下面结合附图,通过具体实施例对本申请技术方案作详细描述。
本发明公开了一种统计应用程序中的函数调用的方法,所述方法应用在统计应用程序中的函数调用的组件中。
参看图1,是本发明提供的一种统计应用程序中的函数调用的方法的流程图,该方法包括:
步骤11,在所述应用程序运行时,利用所述组件中的钩子函数库监控统计调用信息文件MAP文件中的所有函数的函数头在预设时间内各自的调用次数,和所述所有函数的函数头各自的调用时刻。
在具体的实施过程中,本发明的组件注入在所述应用程序的进程中。故而,在应用程序运行时,该组件即可利用组件中的钩子函数库对该应用程序中的所有函数进行监控,进而避免无法对发布后的软件中的函数的调用时间、调用次数进行监控的漏洞。后续本发明会介绍应用在组件中的统计应用程序中的函数调用的具体实施过程,即如何对应用程序的所有函数进行监控统计。在此,本发明先介绍MAP文件的创建。
MAP文件,是事先在使用编译器生成软件(即应用程序)的执行文件时加入生成的。在使用编译器编译软件的代码的时候,可以在编译器选项中加入‘生成MAP文件’这一选项,进而编译器则会根据开发者的操作来生成MAP文件。
其中,MAP文件实际是一个调用信息文件,其包含有该应用程序中所有函数的函数名称、函数地址(即:函数的相对于模块的地址),函数长度,所有的全局变量名,全局变量名的地址等。有了MAP文件,就具有了对应于该模块的所有函数的名称,以及该函数在运行时的内存地址,以及函数的代码的长度信息。有了MAP文件,组件即可以调用MAP文件,进而为对所有函数进行监控,通过使用钩子函数将自身的代码“融入”被监控的程序的进程中,成为目标进程的一个部分,从而可以对程序进行监控,还可以在目标代码中加入自己的逻辑。
作为一种可选的实施方式,钩子函数库可采用Detours库,Detours库是一个HOOK(监控)工具库,里面包含了各类钩子函数,可满足对任一函数进行监控的可能。
下面介绍如何对应用程序的所有函数进行监控统计。
在此之前,需要利用所述钩子函数库的钩子函数监控所述所有函数的函数头。
在监控所有函数的函数头时,本发明使用内联监控方式,其原理是在函数的开头加入一个汇编的“JMP”指令,通过这个挑战则可以跳转到我们插入的代码逻辑中,代码逻辑是组件的组成代码,运行代码逻辑即执行该组件的功能,然后等插入的代码逻辑执行完成后,再跳转到HOOK的函数接着其逻辑继续执行。本发明在插入的代码逻辑中,加入了对函数的调用次数统计信息,用以对函数的调用次数进行统计。例如,可以加入一个变量来统计函数的调用次数,并且没执行一次则计数加1,最终统计完成时,该变量的值则是该段统计时段内函数的调用次数。
另外,本发明也可以记录下当前调用的时刻,后续在函数尾进行监控时也会加入当前调用的时刻,通过函数尾的时刻减去函数头的时刻则可以得到监控的这个函数在执行一次所花费的时间。
本文使用微软提供的开源的内联监控工具Detours(Detours是微软开发的一个HOOK工具库)来实现监控功能。
下面介绍具体的实施过程。
第1步,获取所述组件在终端设备的内存中的起始地址。
对于组件在内存的加载起始地址每次都是不一样的,所以需要先获取组件在终端设备的内存的起始地址。
HMODULE GetModuleHandle(LPCTSTRl pModuleName);
通过调用Windows API函数GetModuleHandle来获取组件的内存起始地址。
其中,参数pModuleName则传入组件的名称。
其中,返回值HMODULE则是组件的内存起始地址。
第2步,读取所述MAP文件中的所有函数的函数名称、函数地址。
其中,所述所有函数的函数地址为各自相对于组件的函数地址。在MAP文件中会有所有函数的名称及函数地址,通过读取MAP文件的内容则可以获取到所有函数的名称和函数地址。
第3步,将所述所有函数的函数地址各自相对于所述组件的函数地址分别和所述组件在内存中的起始地址求和,获得所述所有函数各自的内存地址。其中,所述所有函数各自的内存地址就是所述所有函数各自的函数头。
第4步,利用所述钩子函数库对所述所有函数各自的内存地址进行监控。
故而,在调用时,利用所述钩子函数库监控所述所有函数从各自的内存地址调用的调用次数和调用时刻。
步骤12,利用所述钩子函数库监控统计所述MAP文件中的所有函数的函数尾各自的调用时刻。
在具体的实施过程中,利用所述钩子函数库监控统计所述MAP文件中的所有函数的函数尾各自的调用时刻,包括:读取所述所有函数的函数名称、函数地址、函数长度;
将所述所有函数各自的函数地址和函数长度求和,获得所述所有函数各自的尾地址;
利用所述钩子函数库对所述所有函数各自的尾地址进行监控,获得所述所有函数各自的尾地址的调用时刻。
步骤13,基于所述MAP文件中的所述所有函数的函数头各自的调用时刻以及所述所有函数的函数尾各自的调用时刻,确定出所述所有函数在所述预设时间内的调用时间。
在对MAP中的所有函数的函数头和函数尾进行监控后,并且在函数头有计算每个函数头的调用次数统计,并且在函数头和函数尾都有记录当前调用的时刻,通过对同一个函数的这2个时刻则可以计算出该函数执行一次的时间。所以可以统计软件在一段时间内所有函数的执行次数以及执行时间,并且可以将统计结果输出成文本的形式,从而可以方便的定位软件的性能瓶颈等问题。
基于同一发明构思,本发明还公开了一种统计应用程序中的函数调用的组件,所述组件注入在所述应用程序的进程中,用以对所述应用程序中的所有函数的调用时间和调用次数进行监控。
参看图2,本发明还公开的一种统计应用程序中的函数调用的组件,包括:
第一监控模块21,用于在所述应用程序运行时,利用所述组件中的钩子函数库监控统计调用信息文件MAP文件中的所有函数的函数头在预设时间内各自的调用次数,和所述所有函数的函数头各自的调用时刻;其中,所述组件注入所述应用程序的进程中;
第二监控模块22,用于利用所述钩子函数库监控统计所述MAP文件中的所有函数的函数尾各自的调用时刻;
确定模块23,用于基于所述MAP文件中的所述所有函数的函数头各自的调用时刻以及所述所有函数的函数尾各自的调用时刻,确定出所述所有函数在所述预设时间内的调用时间。
作为一种可选的实施例,所述MAP文件中至少记录了所述所有函数的函数名称、函数地址,函数长度、所有的全局变量、全局变量名的地址。
作为一种可选的实施例,所述组件还包括:
第三监控模块,用于利用所述钩子函数库的钩子函数监控所述所有函数的函数头。
作为一种可选的实施例,所述第三监控模块,包括:
获取模块,用于获取所述组件在终端设备的内存中的起始地址;
读取模块,用于读取所述MAP文件中的所有函数的函数名称、函数地址;其中,所述所有函数的函数地址为各自相对于所述组件的函数地址;
获得模块,用于将所述所有函数的函数地址各自相对于所述组件的函数地址分别和所述组件在内存中的起始地址求和,获得所述所有函数各自的内存地址;所述所有函数各自的内存地址就是所述所有函数各自的函数头;
监控子模块,用于利用所述钩子函数库对所述所有函数各自的内存地址进行监控。
本文提供了一种统计应用程序中的函数调用的方法及组件,来对已经发布的客户端软件来统计每个函数的调用次数及每个函数的调用时间统计。从而无需在软件开发的时候加入函数统计的功能。对于已经发布的软件通过使用本文的方法也可以进行统计函数的调用次数及时间功能。
通过本发明的一个或者多个实施例,本发明具有以下有益效果或者优点:
本发明公开了一种统计应用程序中的函数调用的方法,为了避免发布之后的应用程序无法监控其函数调用情况,所述方法应用在统计应用程序中的函数调用的组件中,用以监控应用程序的函数调用情况。在该应用程序运行时,利用所述组件中的钩子函数库监控统计调用信息文件MAP文件中的所有函数的函数头在预设时间内各自的调用次数,和所有函数的函数头各自的调用时刻;然后利用所述钩子函数库监控统计所述MAP文件中的所有函数的函数尾各自的调用时刻;基于所述MAP文件中的所述所有函数的函数头各自的调用时刻以及所述所有函数的函数尾各自的调用时刻,确定出所述所有函数在所述预设时间内的调用时间。进而,本发明可以在应用程序运行时,实时统计函数的调用情况。
尽管已描述了本申请的优选实施例,但本领域内的普通技术人员一旦得知了基本创造性概念,则可对这些实施例作出另外的变更和修改。所以,所附权利要求意欲解释为包括优选实施例以及落入本申请范围的所有变更和修改。
显然,本领域的技术人员可以对本申请进行各种改动和变型而不脱离本申请的精神和范围。这样,倘若本申请的这些修改和变型属于本申请权利要求及其等同技术的范围之内,则本申请也意图包含这些改动和变型在内。