【摘要】針對變電站系統(tǒng)的軟件穩(wěn)定性和安全性,引入了內(nèi)存檢測技術(shù)的概念,介紹了內(nèi)存泄漏的發(fā)生原因和發(fā)生方式。然后詳細(xì)提出了幾種內(nèi)存檢測測試方法和測試要求。最后介紹了一種測試技術(shù)設(shè)計方案,并在實際工程中得到了應(yīng)用,保證了變電站系統(tǒng)軟件運行的穩(wěn)定性和安全性。
【關(guān)鍵詞】變電站自動化 內(nèi)存泄漏 內(nèi)存檢測 性能監(jiān)視器
0 引言
變電站自動化系統(tǒng)是將變電站的二次設(shè)備(包括測量儀表、信號系統(tǒng)、繼電保護、自動裝置及遠動裝置等)經(jīng)過功能的組合和優(yōu)化設(shè)計,利用先進的計算機技術(shù)、現(xiàn)代電子技術(shù)、通訊技術(shù)和信號處理技術(shù),實現(xiàn)對全變電站的主要設(shè)備和輸、配電線路的自動監(jiān)視、測量、自動控制和微機保護以及與調(diào)度通信等綜合性的自動化功能,在電力系統(tǒng)控制中占有非常重要的地位。因此,對變電站智能設(shè)備(微機保護、測控等)系統(tǒng)的可靠性要求越來越高。
隨著自動化系統(tǒng)的推廣,尤其是數(shù)字化變電站的開展,各個廠家(如許繼電氣、國電南瑞、南瑞繼保、上海ABB等)裝置系統(tǒng)互連機會,變得越來越多,傳統(tǒng)意義上系統(tǒng)主站和子站之間存在的通信不兼容、操作復(fù)雜、現(xiàn)場互聯(lián)爭議多的矛盾越來越少。系統(tǒng)本身軟件的安全性越來越受到重視。軟件運行的可靠性、穩(wěn)定性,經(jīng)實踐證明很大程度上決定于軟件的內(nèi)存等系統(tǒng)資源使用情況,以及軟件運行過程中CPU負(fù)荷率占有情況。軟件內(nèi)存泄漏、占用內(nèi)存過高或CPU負(fù)荷率較高等都會引起系統(tǒng)運行不響應(yīng)用戶操作、軟件自動退出,或系統(tǒng)死機等嚴(yán)重問題。在測試變電站自動化系統(tǒng)操作站、工程師站、遠動站、VQC軟件,以及調(diào)度自動化系統(tǒng),配網(wǎng)自動化系統(tǒng)中都需要對被測軟件運行過程中的內(nèi)存及CPU負(fù)荷率進行監(jiān)視,以測試是否存在內(nèi)存泄漏、CPU負(fù)荷率高等影響系統(tǒng)運行可靠性的問題。
軟件的應(yīng)用越來越廣泛,規(guī)模和復(fù)雜度不斷提高,軟件中的安全缺陷與漏洞也在不斷增多,軟件安全性問題日益突出。內(nèi)存檢測技術(shù)是軟件安全性測試的重要方法,是保證軟件安全性、降低軟件安全風(fēng)險的重要手段。
本文首先介紹了內(nèi)存檢測技術(shù)的相關(guān)概念,然后對內(nèi)存泄漏問題產(chǎn)生原因和發(fā)生方式進行了詳細(xì)剖析,最后以某變電站自動化監(jiān)控軟件為例,給出了內(nèi)存檢測技術(shù)在電力系統(tǒng)軟件中的具體應(yīng)用。
1 內(nèi)存檢測技術(shù)介紹
1.1 內(nèi)存的分配方式
對于不同的編程語言,內(nèi)存的分配方式也不盡相同。以C語言和C++語言為例。
在C語言中,內(nèi)存分配有四個存儲區(qū):
(1)棧。用于存儲函數(shù)體中定義的局部變量,其內(nèi)存資源是有編譯器自動分配和釋放。
(2)堆。采用maUoc、calloc、reaUoc等分配的內(nèi)存資源就是在堆上,這部分內(nèi)存資源使用更加靈活,一般是由程序員根據(jù)需要分配,使用完畢后編寫相應(yīng)代碼釋放,若程序員不釋放,則在程序結(jié)束時有可能由操作系統(tǒng)回收。
(3)全局存儲區(qū)(靜態(tài)存儲區(qū))。用于存放全局變量和靜態(tài)變量,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域,這些內(nèi)存資源需要等到程序結(jié)束時釋放。
(4)常量存儲區(qū)。函數(shù)中使用到的一些常量都存放在常量區(qū),程序結(jié)束后自動釋放。
在C++語言中,內(nèi)存分配則有5個存儲區(qū):
(1)棧。用于存儲那些由編譯器在需要的時候分配,在使用完畢后自動清除的變量。通常是指局部變量、函數(shù)參數(shù)等。
(2)堆。用于存放那些由new分配的內(nèi)存塊,這部分內(nèi)存資源編譯器不會去管理,由應(yīng)用程序去控制。一般一個new就要對應(yīng)一個delete,也就是說一個分配對應(yīng)一個釋放,都是由程序員編寫代碼控制。如果程序員只分配沒有釋放,那么在程序結(jié)束后,操作系統(tǒng)才會自動回收。
(3)自由存儲區(qū)。用于存放由malloc等分配的內(nèi)存塊,它和堆十分相似,不同點在于它是用free來釋放內(nèi)存資源。
(4)全局存儲區(qū)(靜態(tài)存儲區(qū))。用于存放全局變量和靜態(tài)變量,和C語言的區(qū)別在于,全局變量和靜態(tài)變量不分初始化和未初始化,它們共同占用同一塊內(nèi)存區(qū)。
(5)常量存儲區(qū)。用于存放常量,和C語言中一致。
通過比較不同程序設(shè)計語言的內(nèi)存分配方式,我們發(fā)現(xiàn)程序中內(nèi)存的使用是一個相當(dāng)復(fù)雜的過程,不同的變量有不同的存儲區(qū)域,不同的變量有不同的分配方式和釋放方式。那么,內(nèi)存泄漏是如何發(fā)生的呢?
1.2 內(nèi)存泄漏的定義
(1)一般來說的內(nèi)存泄漏是指堆內(nèi)存的泄漏。如1.1中介紹的,在C中,就是指堆存儲區(qū)的泄漏。在C++中,就是指堆和自由存儲區(qū)的泄漏。正是由于這些存儲區(qū)內(nèi)存資源的使用相對靈活,由程序員自主控制,在程序的運行過程中不受操作系統(tǒng)管理,才有了內(nèi)存泄漏發(fā)生的可能。應(yīng)用程序一般使用malloc、realloc、new等函數(shù)從堆中分配一塊內(nèi)存,使用完后,程序必須調(diào)用相應(yīng)的free或delete釋放該內(nèi)存塊,否則,這塊內(nèi)存就不能被回收重用,這塊內(nèi)存就是內(nèi)存泄漏了。
(2)廣義來說,內(nèi)存泄漏不僅僅包含堆內(nèi)存的泄漏,還包括系統(tǒng)資源的泄漏(resource Leak)。從根本上來說,由操作系統(tǒng)分配的對象也消耗內(nèi)存,這些對象占用的內(nèi)存發(fā)生泄漏也屬于內(nèi)存泄漏的范疇。特別是對于消耗核心態(tài)內(nèi)存的對象,更會導(dǎo)致整個操作系統(tǒng)的不穩(wěn)定,這相比其他類型的內(nèi)存泄漏問題更為嚴(yán)重。
1.3 內(nèi)存泄漏的發(fā)生方式
內(nèi)存泄漏有多種發(fā)生方式,不同方式的內(nèi)存泄漏的危害各有不同。
(1)一次性內(nèi)存泄漏。存在內(nèi)存泄漏的代碼在程序運行的整個過程只會被執(zhí)行一次,或者由于算法上的缺陷,導(dǎo)致總會存在一塊且僅有一塊內(nèi)存發(fā)生泄漏。這種一次性內(nèi)存泄漏不會造成內(nèi)存泄漏的堆積,如果不是核心態(tài)內(nèi)存,基本上對程序的穩(wěn)定性和安全性不會產(chǎn)生影響。
(2)偶發(fā)性內(nèi)存泄漏。存在內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會發(fā)生。偶發(fā)性內(nèi)存泄漏一般情況下造成的內(nèi)存泄漏的堆積相對較少,但在某些特定情況下也有可能造成大量的內(nèi)存泄漏堆積,對程序的穩(wěn)定性和安全性有較大的潛在危害。
(3)常發(fā)性內(nèi)存泄漏。存在內(nèi)存泄漏的代碼會被多次執(zhí)行到,每次執(zhí)行的時候都會導(dǎo)致一塊內(nèi)存泄漏。常發(fā)性內(nèi)存泄漏會造成大量的內(nèi)存泄漏堆積,這會大量浪費內(nèi)存資源甚至造成內(nèi)存枯竭,對程序的穩(wěn)定性和安全性有著極大的危害。
(4)隱式內(nèi)存泄漏。程序在運行過程中不停地分配內(nèi)存,直到結(jié)束的時候才釋放。理論上這里沒有發(fā)生內(nèi)存泄漏,因為程序最終釋放了所有申請的內(nèi)存。但對于一個長期運行的程序,不及時釋放內(nèi)存可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存,危害是可想而知的。
1.4 內(nèi)存泄漏測試技術(shù)
由以上內(nèi)容可知,內(nèi)存泄漏確實是一個頑固而致命的問題。特別是對于可靠性、穩(wěn)定性和安全性要求非常高的電力系統(tǒng)軟件,更是不能忽視任何一個內(nèi)存問題的存在,一旦疏忽,勢必造成非常嚴(yán)重的后果“’。所以,在電力系統(tǒng)軟件開發(fā)過程中,必須引進成熟可靠的內(nèi)存泄漏測試技術(shù)。
內(nèi)存泄漏測試技術(shù),就是在電力系統(tǒng)軟件開發(fā)過程中,能有效地發(fā)現(xiàn)和定位內(nèi)存泄漏的測試技術(shù)。
目前,內(nèi)存泄漏的測試方法主要有以下三種:
(1)利用VC內(nèi)建檢測功能檢測內(nèi)存泄漏
具有動態(tài)分配和釋放內(nèi)存的能力是C/C++程序設(shè)計語言的重要特色之一,Visual C++debugger和CRT庫提供了一系列有效的檢測和鑒定內(nèi)存泄漏的工具。
(2)通過專門的測試工具檢測內(nèi)存泄漏
對于開發(fā)一個大型的程序,利用VC內(nèi)建檢測功能是不夠的,還需要借助專業(yè)的內(nèi)存泄漏檢測工具進行更全面的內(nèi)存泄漏檢測。采用專業(yè)的內(nèi)存測試工具,一般需要在測試工具環(huán)境下進行程序的編譯、調(diào)試和運行進行動態(tài)測試,這些溯試工具會自動給出內(nèi)存泄漏的測試結(jié)果,甚至可以定位產(chǎn)生內(nèi)存泄漏的代碼位置。比如采用目標(biāo)代碼插入(Code Injection)技術(shù)的Compuware公司的BoundsChecker和Rational公司的Purify都是非常優(yōu)秀的內(nèi)存測試工具。
(3)利用性能監(jiān)視器(Performance Monitor)監(jiān)視內(nèi)存使用數(shù)據(jù)
以上兩種測試方法對于顯式內(nèi)存泄漏來說是很有效的,但是對于隱式內(nèi)存泄漏來說就顯得有些無能為力了。使用操作系統(tǒng)的性能監(jiān)視器(Performance Monitor)可以實時監(jiān)視內(nèi)存的使用情況,通過查看內(nèi)存的使用數(shù)據(jù)來判斷是否存在內(nèi)存泄漏,這種方法只能證明內(nèi)存泄漏的存在,卻不能定位內(nèi)存泄漏的位置,一旦發(fā)現(xiàn)有內(nèi)存泄漏,需要借助其他方法進一步進行分析定位。
綜合以上三種內(nèi)存檢測方法,我們發(fā)現(xiàn)每種方法都有其優(yōu)缺點,對于內(nèi)存泄漏這個大而復(fù)雜的問題,往往需要多種方法相結(jié)合,才能達到更好的效果和效率。
2 一種基于電力系統(tǒng)監(jiān)控軟件的內(nèi)存檢測模型
下面給出一種基于電力系統(tǒng)監(jiān)控軟件的內(nèi)存檢測模型,其主要思想是利用性能監(jiān)視器(Performance Monitor)在一段時間內(nèi)實時監(jiān)視該軟件各進程的運行數(shù)據(jù),實時記錄各進程的CPU負(fù)荷率信息和內(nèi)存使用數(shù)據(jù)。
首先,我們需要配置準(zhǔn)備監(jiān)視的進程個數(shù)以及每個進程的窗口標(biāo)題或進程ID,還需要配置各進程的告警門檻和記錄時間間隔。
配置完必要信息,就可以打開日志文件和定時器開始拷機測試了。
在拷機過程中,實時監(jiān)視并按照配置的時間間隔記錄每個進程的CPU負(fù)荷和內(nèi)存數(shù)據(jù)到日志文件。如果CPU使用率超過告警門檻則輸出告警信息并記錄到日志文件。如果內(nèi)存增長定值超過告警門檻則輸出告警信息并記錄到日志文件。
在設(shè)定時間內(nèi)依次記錄每個進程的數(shù)據(jù),最后關(guān)閉定時器,關(guān)閉日志文件,拷機檢測結(jié)束。
3 該內(nèi)存檢測方法的實際應(yīng)用
下面是一組上述內(nèi)存檢測模型在某變電站監(jiān)控軟件中的應(yīng)用。
隨著系統(tǒng)運行時間逐漸增加,系統(tǒng)所占用的內(nèi)存也逐漸增大。表明軟件系統(tǒng)存在內(nèi)存泄露,長時間運行可能會耗盡內(nèi)存,導(dǎo)致系統(tǒng)出現(xiàn)死機。經(jīng)過對軟件進行優(yōu)化,解決了內(nèi)存泄露的問題,目前系統(tǒng)運行穩(wěn)定。
4 結(jié)束語
隨著變電站系統(tǒng)的自動化程度越來越高,特別是大容量、大系統(tǒng)的變電站系統(tǒng)的投入運行,對監(jiān)控系統(tǒng)的穩(wěn)定性和安全性的要求也會愈來愈高。變電站系統(tǒng)是需要長期運行的系統(tǒng),如果存在內(nèi)存泄露,那后果是不言而喻的。內(nèi)存檢測作為軟件穩(wěn)定性和安全性要求的重要方面,今后也會越來越引起重視,得到廣泛的應(yīng)用。