论文部分内容阅读
【摘要】针对变电站系统的软件稳定性和安全性,引入了内存检测技术的概念,介绍了内存泄漏的发生原因和发生方式。然后详细提出了几种内存检测测试方法和测试要求。最后介绍了一种测试技术设计方案,并在实际工程中得到了应用,保证了变电站系统软件运行的稳定性和安全性。
【关键词】变电站自动化 内存泄漏 内存检测 性能监视器
0 引言
变电站自动化系统是将变电站的二次设备(包括测量仪表、信号系统、继电保护、自动装置及远动装置等)经过功能的组合和优化设计,利用先进的计算机技术、现代电子技术、通讯技术和信号处理技术,实现对全变电站的主要设备和输、配电线路的自动监视、测量、自动控制和微机保护以及与调度通信等综合性的自动化功能,在电力系统控制中占有非常重要的地位。因此,对变电站智能设备(微机保护、测控等)系统的可靠性要求越来越高。
随着自动化系统的推广,尤其是数字化变电站的开展,各个厂家(如许继电气、国电南瑞、南瑞继保、上海ABB等)装置系统互连机会,变得越来越多,传统意义上系统主站和子站之间存在的通信不兼容、操作复杂、现场互联争议多的矛盾越来越少。系统本身软件的安全性越来越受到重视。软件运行的可靠性、稳定性,经实践证明很大程度上决定于软件的内存等系统资源使用情况,以及软件运行过程中CPU负荷率占有情况。软件内存泄漏、占用内存过高或CPU负荷率较高等都会引起系统运行不响应用户操作、软件自动退出,或系统死机等严重问题。在测试变电站自动化系统操作站、工程师站、远动站、VQC软件,以及调度自动化系统,配网自动化系统中都需要对被测软件运行过程中的内存及CPU负荷率进行监视,以测试是否存在内存泄漏、CPU负荷率高等影响系统运行可靠性的问题。
软件的应用越来越广泛,规模和复杂度不断提高,软件中的安全缺陷与漏洞也在不断增多,软件安全性问题日益突出。内存检测技术是软件安全性测试的重要方法,是保证软件安全性、降低软件安全风险的重要手段。
本文首先介绍了内存检测技术的相关概念,然后对内存泄漏问题产生原因和发生方式进行了详细剖析,最后以某变电站自动化监控软件为例,给出了内存检测技术在电力系统软件中的具体应用。
1 内存检测技术介绍
1.1 内存的分配方式
对于不同的编程语言,内存的分配方式也不尽相同。以C语言和C++语言为例。
在C语言中,内存分配有四个存储区:
(1)栈。用于存储函数体中定义的局部变量,其内存资源是有编译器自动分配和释放。
(2)堆。采用maUoc、calloc、reaUoc等分配的内存资源就是在堆上,这部分内存资源使用更加灵活,一般是由程序员根据需要分配,使用完毕后编写相应代码释放,若程序员不释放,则在程序结束时有可能由操作系统回收。
(3)全局存储区(静态存储区)。用于存放全局变量和静态变量,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,这些内存资源需要等到程序结束时释放。
(4)常量存储区。函数中使用到的一些常量都存放在常量区,程序结束后自动释放。
在C++语言中,内存分配则有5个存储区:
(1)栈。用于存储那些由编译器在需要的时候分配,在使用完毕后自动清除的变量。通常是指局部变量、函数参数等。
(2)堆。用于存放那些由new分配的内存块,这部分内存资源编译器不会去管理,由应用程序去控制。一般一个new就要对应一个delete,也就是说一个分配对应一个释放,都是由程序员编写代码控制。如果程序员只分配没有释放,那么在程序结束后,操作系统才会自动回收。
(3)自由存储区。用于存放由malloc等分配的内存块,它和堆十分相似,不同点在于它是用free来释放内存资源。
(4)全局存储区(静态存储区)。用于存放全局变量和静态变量,和C语言的区别在于,全局变量和静态变量不分初始化和未初始化,它们共同占用同一块内存区。
(5)常量存储区。用于存放常量,和C语言中一致。
通过比较不同程序设计语言的内存分配方式,我们发现程序中内存的使用是一个相当复杂的过程,不同的变量有不同的存储区域,不同的变量有不同的分配方式和释放方式。那么,内存泄漏是如何发生的呢?
1.2 内存泄漏的定义
(1)一般来说的内存泄漏是指堆内存的泄漏。如1.1中介绍的,在C中,就是指堆存储区的泄漏。在C++中,就是指堆和自由存储区的泄漏。正是由于这些存储区内存资源的使用相对灵活,由程序员自主控制,在程序的运行过程中不受操作系统管理,才有了内存泄漏发生的可能。应用程序一般使用malloc、realloc、new等函数从堆中分配一块内存,使用完后,程序必须调用相应的free或delete释放该内存块,否则,这块内存就不能被回收重用,这块内存就是内存泄漏了。
(2)广义来说,内存泄漏不仅仅包含堆内存的泄漏,还包括系统资源的泄漏(resource Leak)。从根本上来说,由操作系统分配的对象也消耗内存,这些对象占用的内存发生泄漏也属于内存泄漏的范畴。特别是对于消耗核心态内存的对象,更会导致整个操作系统的不稳定,这相比其他类型的内存泄漏问题更为严重。
1.3 内存泄漏的发生方式
内存泄漏有多种发生方式,不同方式的内存泄漏的危害各有不同。
(1)一次性内存泄漏。存在内存泄漏的代码在程序运行的整个过程只会被执行一次,或者由于算法上的缺陷,导致总会存在一块且仅有一块内存发生泄漏。这种一次性内存泄漏不会造成内存泄漏的堆积,如果不是核心态内存,基本上对程序的稳定性和安全性不会产生影响。
(2)偶发性内存泄漏。存在内存泄漏的代码只有在某些特定环境或操作过程下才会发生。偶发性内存泄漏一般情况下造成的内存泄漏的堆积相对较少,但在某些特定情况下也有可能造成大量的内存泄漏堆积,对程序的稳定性和安全性有较大的潜在危害。
(3)常发性内存泄漏。存在内存泄漏的代码会被多次执行到,每次执行的时候都会导致一块内存泄漏。常发性内存泄漏会造成大量的内存泄漏堆积,这会大量浪费内存资源甚至造成内存枯竭,对程序的稳定性和安全性有着极大的危害。
(4)隐式内存泄漏。程序在运行过程中不停地分配内存,直到结束的时候才释放。理论上这里没有发生内存泄漏,因为程序最终释放了所有申请的内存。但对于一个长期运行的程序,不及时释放内存可能导致最终耗尽系统的所有内存,危害是可想而知的。
1.4 内存泄漏测试技术
由以上内容可知,内存泄漏确实是一个顽固而致命的问题。特别是对于可靠性、稳定性和安全性要求非常高的电力系统软件,更是不能忽视任何一个内存问题的存在,一旦疏忽,势必造成非常严重的后果“’。所以, 在电力系统软件开发过程中,必须引进成熟可靠的内存泄漏测试技术。
内存泄漏测试技术,就是在电力系统软件开发过程中,能有效地发现和定位内存泄漏的测试技术。
目前,内存泄漏的测试方法主要有以下三种:
(1)利用VC内建检测功能检测内存泄漏
具有动态分配和释放内存的能力是C/C++程序设计语言的重要特色之一,Visual C++debugger和CRT库提供了一系列有效的检测和鉴定内存泄漏的工具。
(2)通过专门的测试工具检测内存泄漏
对于开发一个大型的程序,利用VC内建检测功能是不够的,还需要借助专业的内存泄漏检测工具进行更全面的内存泄漏检测。采用专业的内存测试工具,一般需要在测试工具环境下进行程序的编译、调试和运行进行动态测试,这些溯试工具会自动给出内存泄漏的测试结果,甚至可以定位产生内存泄漏的代码位置。比如采用目标代码插入(Code Injection)技术的Compuware公司的BoundsChecker和Rational公司的Purify都是非常优秀的内存测试工具。
(3)利用性能监视器(Performance Monitor)监视内存使用数据
以上两种测试方法对于显式内存泄漏来说是很有效的,但是对于隐式内存泄漏来说就显得有些无能为力了。使用操作系统的性能监视器(Performance Monitor)可以实时监视内存的使用情况,通过查看内存的使用数据来判断是否存在内存泄漏,这种方法只能证明内存泄漏的存在,却不能定位内存泄漏的位置,一旦发现有内存泄漏,需要借助其他方法进一步进行分析定位。
综合以上三种内存检测方法,我们发现每种方法都有其优缺点,对于内存泄漏这个大而复杂的问题,往往需要多种方法相结合,才能达到更好的效果和效率。
2 一种基于电力系统监控软件的内存检测模型
下面给出一种基于电力系统监控软件的内存检测模型,其主要思想是利用性能监视器(Performance Monitor)在一段时间内实时监视该软件各进程的运行数据,实时记录各进程的CPU负荷率信息和内存使用数据。
首先,我们需要配置准备监视的进程个数以及每个进程的窗口标题或进程ID,还需要配置各进程的告警门槛和记录时间间隔。
配置完必要信息,就可以打开日志文件和定时器开始拷机测试了。
在拷机过程中,实时监视并按照配置的时间间隔记录每个进程的CPU负荷和内存数据到日志文件。如果CPU使用率超过告警门槛则输出告警信息并记录到日志文件。如果内存增长定值超过告警门槛则输出告警信息并记录到日志文件。
在设定时间内依次记录每个进程的数据,最后关闭定时器,关闭日志文件,拷机检测结束。
3 该内存检测方法的实际应用
下面是一组上述内存检测模型在某变电站监控软件中的应用。
随着系统运行时间逐渐增加,系统所占用的内存也逐渐增大。表明软件系统存在内存泄露,长时间运行可能会耗尽内存,导致系统出现死机。经过对软件进行优化,解决了内存泄露的问题,目前系统运行稳定。
4 结束语
随着变电站系统的自动化程度越来越高,特别是大容量、大系统的变电站系统的投入运行,对监控系统的稳定性和安全性的要求也会愈来愈高。变电站系统是需要长期运行的系统,如果存在内存泄露,那后果是不言而喻的。内存检测作为软件稳定性和安全性要求的重要方面,今后也会越来越引起重视,得到广泛的应用。
【关键词】变电站自动化 内存泄漏 内存检测 性能监视器
0 引言
变电站自动化系统是将变电站的二次设备(包括测量仪表、信号系统、继电保护、自动装置及远动装置等)经过功能的组合和优化设计,利用先进的计算机技术、现代电子技术、通讯技术和信号处理技术,实现对全变电站的主要设备和输、配电线路的自动监视、测量、自动控制和微机保护以及与调度通信等综合性的自动化功能,在电力系统控制中占有非常重要的地位。因此,对变电站智能设备(微机保护、测控等)系统的可靠性要求越来越高。
随着自动化系统的推广,尤其是数字化变电站的开展,各个厂家(如许继电气、国电南瑞、南瑞继保、上海ABB等)装置系统互连机会,变得越来越多,传统意义上系统主站和子站之间存在的通信不兼容、操作复杂、现场互联争议多的矛盾越来越少。系统本身软件的安全性越来越受到重视。软件运行的可靠性、稳定性,经实践证明很大程度上决定于软件的内存等系统资源使用情况,以及软件运行过程中CPU负荷率占有情况。软件内存泄漏、占用内存过高或CPU负荷率较高等都会引起系统运行不响应用户操作、软件自动退出,或系统死机等严重问题。在测试变电站自动化系统操作站、工程师站、远动站、VQC软件,以及调度自动化系统,配网自动化系统中都需要对被测软件运行过程中的内存及CPU负荷率进行监视,以测试是否存在内存泄漏、CPU负荷率高等影响系统运行可靠性的问题。
软件的应用越来越广泛,规模和复杂度不断提高,软件中的安全缺陷与漏洞也在不断增多,软件安全性问题日益突出。内存检测技术是软件安全性测试的重要方法,是保证软件安全性、降低软件安全风险的重要手段。
本文首先介绍了内存检测技术的相关概念,然后对内存泄漏问题产生原因和发生方式进行了详细剖析,最后以某变电站自动化监控软件为例,给出了内存检测技术在电力系统软件中的具体应用。
1 内存检测技术介绍
1.1 内存的分配方式
对于不同的编程语言,内存的分配方式也不尽相同。以C语言和C++语言为例。
在C语言中,内存分配有四个存储区:
(1)栈。用于存储函数体中定义的局部变量,其内存资源是有编译器自动分配和释放。
(2)堆。采用maUoc、calloc、reaUoc等分配的内存资源就是在堆上,这部分内存资源使用更加灵活,一般是由程序员根据需要分配,使用完毕后编写相应代码释放,若程序员不释放,则在程序结束时有可能由操作系统回收。
(3)全局存储区(静态存储区)。用于存放全局变量和静态变量,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,这些内存资源需要等到程序结束时释放。
(4)常量存储区。函数中使用到的一些常量都存放在常量区,程序结束后自动释放。
在C++语言中,内存分配则有5个存储区:
(1)栈。用于存储那些由编译器在需要的时候分配,在使用完毕后自动清除的变量。通常是指局部变量、函数参数等。
(2)堆。用于存放那些由new分配的内存块,这部分内存资源编译器不会去管理,由应用程序去控制。一般一个new就要对应一个delete,也就是说一个分配对应一个释放,都是由程序员编写代码控制。如果程序员只分配没有释放,那么在程序结束后,操作系统才会自动回收。
(3)自由存储区。用于存放由malloc等分配的内存块,它和堆十分相似,不同点在于它是用free来释放内存资源。
(4)全局存储区(静态存储区)。用于存放全局变量和静态变量,和C语言的区别在于,全局变量和静态变量不分初始化和未初始化,它们共同占用同一块内存区。
(5)常量存储区。用于存放常量,和C语言中一致。
通过比较不同程序设计语言的内存分配方式,我们发现程序中内存的使用是一个相当复杂的过程,不同的变量有不同的存储区域,不同的变量有不同的分配方式和释放方式。那么,内存泄漏是如何发生的呢?
1.2 内存泄漏的定义
(1)一般来说的内存泄漏是指堆内存的泄漏。如1.1中介绍的,在C中,就是指堆存储区的泄漏。在C++中,就是指堆和自由存储区的泄漏。正是由于这些存储区内存资源的使用相对灵活,由程序员自主控制,在程序的运行过程中不受操作系统管理,才有了内存泄漏发生的可能。应用程序一般使用malloc、realloc、new等函数从堆中分配一块内存,使用完后,程序必须调用相应的free或delete释放该内存块,否则,这块内存就不能被回收重用,这块内存就是内存泄漏了。
(2)广义来说,内存泄漏不仅仅包含堆内存的泄漏,还包括系统资源的泄漏(resource Leak)。从根本上来说,由操作系统分配的对象也消耗内存,这些对象占用的内存发生泄漏也属于内存泄漏的范畴。特别是对于消耗核心态内存的对象,更会导致整个操作系统的不稳定,这相比其他类型的内存泄漏问题更为严重。
1.3 内存泄漏的发生方式
内存泄漏有多种发生方式,不同方式的内存泄漏的危害各有不同。
(1)一次性内存泄漏。存在内存泄漏的代码在程序运行的整个过程只会被执行一次,或者由于算法上的缺陷,导致总会存在一块且仅有一块内存发生泄漏。这种一次性内存泄漏不会造成内存泄漏的堆积,如果不是核心态内存,基本上对程序的稳定性和安全性不会产生影响。
(2)偶发性内存泄漏。存在内存泄漏的代码只有在某些特定环境或操作过程下才会发生。偶发性内存泄漏一般情况下造成的内存泄漏的堆积相对较少,但在某些特定情况下也有可能造成大量的内存泄漏堆积,对程序的稳定性和安全性有较大的潜在危害。
(3)常发性内存泄漏。存在内存泄漏的代码会被多次执行到,每次执行的时候都会导致一块内存泄漏。常发性内存泄漏会造成大量的内存泄漏堆积,这会大量浪费内存资源甚至造成内存枯竭,对程序的稳定性和安全性有着极大的危害。
(4)隐式内存泄漏。程序在运行过程中不停地分配内存,直到结束的时候才释放。理论上这里没有发生内存泄漏,因为程序最终释放了所有申请的内存。但对于一个长期运行的程序,不及时释放内存可能导致最终耗尽系统的所有内存,危害是可想而知的。
1.4 内存泄漏测试技术
由以上内容可知,内存泄漏确实是一个顽固而致命的问题。特别是对于可靠性、稳定性和安全性要求非常高的电力系统软件,更是不能忽视任何一个内存问题的存在,一旦疏忽,势必造成非常严重的后果“’。所以, 在电力系统软件开发过程中,必须引进成熟可靠的内存泄漏测试技术。
内存泄漏测试技术,就是在电力系统软件开发过程中,能有效地发现和定位内存泄漏的测试技术。
目前,内存泄漏的测试方法主要有以下三种:
(1)利用VC内建检测功能检测内存泄漏
具有动态分配和释放内存的能力是C/C++程序设计语言的重要特色之一,Visual C++debugger和CRT库提供了一系列有效的检测和鉴定内存泄漏的工具。
(2)通过专门的测试工具检测内存泄漏
对于开发一个大型的程序,利用VC内建检测功能是不够的,还需要借助专业的内存泄漏检测工具进行更全面的内存泄漏检测。采用专业的内存测试工具,一般需要在测试工具环境下进行程序的编译、调试和运行进行动态测试,这些溯试工具会自动给出内存泄漏的测试结果,甚至可以定位产生内存泄漏的代码位置。比如采用目标代码插入(Code Injection)技术的Compuware公司的BoundsChecker和Rational公司的Purify都是非常优秀的内存测试工具。
(3)利用性能监视器(Performance Monitor)监视内存使用数据
以上两种测试方法对于显式内存泄漏来说是很有效的,但是对于隐式内存泄漏来说就显得有些无能为力了。使用操作系统的性能监视器(Performance Monitor)可以实时监视内存的使用情况,通过查看内存的使用数据来判断是否存在内存泄漏,这种方法只能证明内存泄漏的存在,却不能定位内存泄漏的位置,一旦发现有内存泄漏,需要借助其他方法进一步进行分析定位。
综合以上三种内存检测方法,我们发现每种方法都有其优缺点,对于内存泄漏这个大而复杂的问题,往往需要多种方法相结合,才能达到更好的效果和效率。
2 一种基于电力系统监控软件的内存检测模型
下面给出一种基于电力系统监控软件的内存检测模型,其主要思想是利用性能监视器(Performance Monitor)在一段时间内实时监视该软件各进程的运行数据,实时记录各进程的CPU负荷率信息和内存使用数据。
首先,我们需要配置准备监视的进程个数以及每个进程的窗口标题或进程ID,还需要配置各进程的告警门槛和记录时间间隔。
配置完必要信息,就可以打开日志文件和定时器开始拷机测试了。
在拷机过程中,实时监视并按照配置的时间间隔记录每个进程的CPU负荷和内存数据到日志文件。如果CPU使用率超过告警门槛则输出告警信息并记录到日志文件。如果内存增长定值超过告警门槛则输出告警信息并记录到日志文件。
在设定时间内依次记录每个进程的数据,最后关闭定时器,关闭日志文件,拷机检测结束。
3 该内存检测方法的实际应用
下面是一组上述内存检测模型在某变电站监控软件中的应用。
随着系统运行时间逐渐增加,系统所占用的内存也逐渐增大。表明软件系统存在内存泄露,长时间运行可能会耗尽内存,导致系统出现死机。经过对软件进行优化,解决了内存泄露的问题,目前系统运行稳定。
4 结束语
随着变电站系统的自动化程度越来越高,特别是大容量、大系统的变电站系统的投入运行,对监控系统的稳定性和安全性的要求也会愈来愈高。变电站系统是需要长期运行的系统,如果存在内存泄露,那后果是不言而喻的。内存检测作为软件稳定性和安全性要求的重要方面,今后也会越来越引起重视,得到广泛的应用。