專利名稱::面向Xen環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法及其實(shí)現(xiàn)系統(tǒng)的制作方法
技術(shù)領(lǐng)域:
:本發(fā)明涉及虛擬化軟件測(cè)試
技術(shù)領(lǐng)域:
,特別是一種面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法及系統(tǒng)。
背景技術(shù):
:Intel與AMD分別提供了硬件輔助虛擬化技術(shù)(Virtualization),使原本互不兼容的各類大型主機(jī)虛擬化技術(shù)逐步惠及X86架構(gòu)微型計(jì)算機(jī)系統(tǒng),通過虛擬機(jī)管理器(VMM)虛擬所有硬件接口,基于物理硬件之上生成可以獨(dú)立運(yùn)行客戶操作系統(tǒng)(GuestOS)的虛擬機(jī)(VM),以VMM為中心使PC服務(wù)器平臺(tái)虛擬化,虛擬化技術(shù)為各種應(yīng)用提供高性能和高可靠的廉價(jià)服務(wù)器,也為當(dāng)前云計(jì)算提供了可行的技術(shù)支持,比如VMware、Citrix的各種云計(jì)算解決方案。虛擬化應(yīng)用環(huán)境的代價(jià)越來越低,虛擬化技術(shù)向人們展示了廣闊的應(yīng)用前景。虛擬機(jī)(VM)是指在一個(gè)硬件平臺(tái)上模擬多個(gè)獨(dú)立的、ISA結(jié)構(gòu)和實(shí)際硬件相同的虛擬硬件系統(tǒng),在每一個(gè)虛擬硬件系統(tǒng)上都可以運(yùn)行不同的操作系統(tǒng),即客戶操作系統(tǒng)(GuestOS),這些GuestOS通過VMM訪問實(shí)際的物理資源。因而整個(gè)虛擬機(jī)系統(tǒng)是以VMM為中心來實(shí)施資源的管理與控制。在各種虛擬機(jī)環(huán)境中運(yùn)行的系統(tǒng)大都是長時(shí)間不停機(jī)系統(tǒng),如通信領(lǐng)域軟件、嵌入式敏感系統(tǒng)等行業(yè)性軟件、運(yùn)行在云集群服務(wù)器上的服務(wù)及各種應(yīng)用程序,存在一個(gè)非常嚴(yán)重的挑戰(zhàn)尚缺少可以在虛擬計(jì)算環(huán)境下檢測(cè)系統(tǒng)可靠性,特別是最可能使系統(tǒng)崩潰的內(nèi)存泄漏可行的檢測(cè)方法。內(nèi)存泄漏會(huì)帶來嚴(yán)重的后果,導(dǎo)致系統(tǒng)提供服務(wù)延遲緩慢,經(jīng)常會(huì)發(fā)生資源耗竭而導(dǎo)致整個(gè)系統(tǒng)崩潰。鑒于運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)的重要性,國內(nèi)外做了很多這方面的工作。這些工作根據(jù)研究對(duì)象所處的狀態(tài),基本分為兩類第一類是基于用戶態(tài)的運(yùn)行時(shí)動(dòng)態(tài)檢測(cè)。這類方法都是基于一種具體的編程語言,在某種平臺(tái)操作系統(tǒng)上對(duì)應(yīng)用系統(tǒng)進(jìn)行插樁或嵌入診斷信息或嵌入對(duì)操作系統(tǒng)相關(guān)操作的監(jiān)控,都需要重新編譯才能對(duì)可能的內(nèi)存泄漏進(jìn)行判斷分析。國內(nèi)典型的有南京大學(xué)徐寶文等人給出了基于源代碼插樁的C程序內(nèi)存使用錯(cuò)誤動(dòng)態(tài)檢測(cè)方法;王勇等人提出了一種統(tǒng)一的內(nèi)存錯(cuò)誤檢測(cè)模型和接口;西安交通大學(xué)馮博琴等人實(shí)現(xiàn)了一個(gè)Linux平臺(tái)下針對(duì)C/C++語言的動(dòng)態(tài)內(nèi)存檢測(cè)模塊,以檢測(cè)內(nèi)存泄漏、內(nèi)存寫溢出、釋放野指針和內(nèi)存管理函數(shù)的不匹配等問題;中國科學(xué)技術(shù)大學(xué)孔德光等人實(shí)現(xiàn)了一個(gè)堆內(nèi)存泄漏檢測(cè)工具,采用紅黑樹管理所分配的堆內(nèi)存,動(dòng)態(tài)跟蹤程序在執(zhí)行過程中堆的分配釋放情況;華南理工大學(xué)劉發(fā)貴等人實(shí)現(xiàn)一個(gè)嵌入式Linux平臺(tái)下數(shù)據(jù)采集和測(cè)試分離的交叉測(cè)試的嵌入式軟件動(dòng)態(tài)內(nèi)存檢測(cè)工具。以上工作大多只是針對(duì)特定的語言、特定的操作系統(tǒng)或特定的硬件環(huán)境。國外最典型的工作有Purify、Jprobe、Jprofiler、Insure++、BoundsChecker、CTrigger>PENELOPE等等。另一類是基于系統(tǒng)內(nèi)核的運(yùn)行時(shí)動(dòng)態(tài)檢測(cè)。這類方法認(rèn)為內(nèi)存泄漏的本質(zhì)是應(yīng)用程序的不合理的內(nèi)存資源使用造成的,通過對(duì)操作系統(tǒng)內(nèi)核中內(nèi)存資源的系統(tǒng)調(diào)用分析進(jìn)行內(nèi)存泄漏的檢測(cè)。這種檢測(cè)要通過捕捉系統(tǒng)調(diào)用因而相對(duì)更困難。伊利諾伊大學(xué)香檳分校YuanyuanZhou等提出一種SafeMem的方法檢測(cè)內(nèi)存泄漏,需要結(jié)合內(nèi)存控制器ECC的糾錯(cuò)功能,對(duì)程序的內(nèi)存泄漏進(jìn)行快速有效的動(dòng)態(tài)監(jiān)視。在程序運(yùn)行時(shí)記錄程序動(dòng)態(tài)分配的內(nèi)存資源和釋放信息,然后分析是否存在內(nèi)存泄露。通過在Linux中加入三個(gè)系統(tǒng)調(diào)用WatchMemory()>DisableffatchMemory()和RegisterECCFaultHanderO,調(diào)用WatchMemory時(shí)disableECC功能,并將內(nèi)存地址對(duì)應(yīng)的內(nèi)存控制器緩沖的32位或64位數(shù)據(jù)修改,但不改ECCcode,這樣下次再訪問該內(nèi)存地址位置時(shí),內(nèi)存控制器檢驗(yàn)ECC得出的ECCcode與控制器中的原ECCcode不一致,并且是多位不一致,所以給CPU發(fā)中斷報(bào)錯(cuò),使用ECC注冊(cè)的RegisterECCFaultHanderO處理程序進(jìn)行處理,最后調(diào)用DisableWatchMemory恢復(fù)ECC功能。實(shí)驗(yàn)結(jié)果比使用Purify檢測(cè)提高了很多。使用ECC的方法很新穎,但是它需要針對(duì)特定的內(nèi)存控制器設(shè)計(jì),目前通用性還不好。哈佛大學(xué)的Bungale在文獻(xiàn)提出了一種在虛擬機(jī)管理器之上的操作系統(tǒng)內(nèi)核級(jí)的調(diào)試機(jī)制PinOS。該方法不僅實(shí)現(xiàn)了用戶態(tài)的監(jiān)控,也擴(kuò)展到了內(nèi)核級(jí)的全狀態(tài)監(jiān)控,使得其性能下降很大,大多數(shù)情況下降低到5060倍,這限制了其在真實(shí)環(huán)境中使用。還有Swaminathan提出基于虛擬化可以優(yōu)化軟件開發(fā)的測(cè)試過程,北京大學(xué)的汪小林提出了一種基于虛擬機(jī)管理器進(jìn)行內(nèi)存泄漏監(jiān)控的方法,并在KVM虛擬平臺(tái)上進(jìn)行了實(shí)現(xiàn)。為了解決這一科學(xué)問題,需要考慮虛擬化計(jì)算環(huán)境平臺(tái)兼具開放性、復(fù)雜性和動(dòng)態(tài)性的特征。Xen起源于2002年由劍橋大學(xué)主持的開源虛擬化項(xiàng)目,2007年Citrix公司發(fā)布了Xen3.1版,標(biāo)志著Xen真正走向成熟,Xen已獲得了業(yè)界的廣泛認(rèn)可與應(yīng)用。傳統(tǒng)的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法受到虛擬計(jì)算平臺(tái)應(yīng)用復(fù)雜、硬件需求千差萬別等各種條件的約束。本發(fā)明在研究現(xiàn)有內(nèi)存泄漏動(dòng)態(tài)檢測(cè)方法的基礎(chǔ)上,采用Xen虛擬化技術(shù),提出一種面向Xen虛擬計(jì)算環(huán)境的內(nèi)存泄漏檢測(cè)VMLD(VirtualizationMemoryLeakDetecting)方法。
發(fā)明內(nèi)容本發(fā)明的目的在于提供一種面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法及系統(tǒng),該不僅適用范圍廣,可以實(shí)現(xiàn)跨平臺(tái)的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè),而且實(shí)現(xiàn)方法簡單,對(duì)現(xiàn)有操作系統(tǒng)改動(dòng)小,適用強(qiáng)。為實(shí)現(xiàn)上述目的,本發(fā)明的技術(shù)方案是一種面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法,包括以下步驟步驟1:動(dòng)態(tài)分析受監(jiān)控程序的內(nèi)存使用行為,對(duì)內(nèi)存對(duì)象進(jìn)行分組,形成多個(gè)內(nèi)存對(duì)象組,并對(duì)各內(nèi)存對(duì)象組相關(guān)信息進(jìn)行維護(hù)和更新;所述內(nèi)存對(duì)象是指經(jīng)系統(tǒng)調(diào)用分配的內(nèi)存塊;所述內(nèi)存對(duì)象生命期是指內(nèi)存對(duì)象從被分配到被釋放的這段時(shí)間;所述內(nèi)存對(duì)象組是內(nèi)存對(duì)象的集合,每個(gè)內(nèi)存對(duì)象都采用一個(gè)元組(size,callChain)來表示,size表示內(nèi)存對(duì)象的大小,callChain表示在分配內(nèi)存對(duì)象時(shí)的棧調(diào)用(call_stack);步驟2:基于觀測(cè)到的行為特征檢測(cè)潛在的內(nèi)存泄漏;步驟3:依據(jù)相關(guān)規(guī)則進(jìn)行內(nèi)存泄漏判定。在本發(fā)明一實(shí)施例中,動(dòng)態(tài)分析受監(jiān)控程序的內(nèi)存使用行為,對(duì)各內(nèi)存對(duì)象組相關(guān)信息進(jìn)行維護(hù)和更新的方法為步驟1.1:對(duì)于每一個(gè)內(nèi)存對(duì)象組,對(duì)其內(nèi)存分配與釋放的行為實(shí)施收集,記錄相關(guān)信息,包括生命期信息、內(nèi)存使用信息;所述生命期信息包括內(nèi)存對(duì)象組的最大生命期maxLifeTime、最大生命期的穩(wěn)定時(shí)間stableTime,所有的時(shí)間都以CPU時(shí)間來度量;所述內(nèi)存使用信息包括內(nèi)存對(duì)象組內(nèi)的活內(nèi)存對(duì)象信息、最后分配時(shí)間、內(nèi)存對(duì)象組占用的總內(nèi)存空間大??;步驟1.2:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一個(gè)活內(nèi)存對(duì)象,記錄其內(nèi)存分配時(shí)間,同一個(gè)內(nèi)存對(duì)象組內(nèi)所有活內(nèi)存對(duì)象都以雙向鏈表的形式表示,以便快速查找;步驟1.3:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一次內(nèi)存分配,即一個(gè)新的活內(nèi)存對(duì)象添加到所述雙向鏈表后,對(duì)內(nèi)存對(duì)象組的關(guān)聯(lián)信息進(jìn)行更新,包括活內(nèi)存對(duì)象信息、最后分配時(shí)間、內(nèi)存對(duì)象組占用的總內(nèi)存空間大小;步驟1.4:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一次內(nèi)存釋放,也對(duì)內(nèi)存對(duì)象組的關(guān)聯(lián)信息進(jìn)行相應(yīng)的更新,包括活內(nèi)存對(duì)象信息、內(nèi)存對(duì)象組占用的總空間大小,同時(shí)通過計(jì)算被釋放內(nèi)存的分配時(shí)間與當(dāng)前時(shí)間的差值,求得被釋放內(nèi)存的生命期IifeTime;步驟1.5:如果被釋放內(nèi)存的IifeTime少于所在內(nèi)存對(duì)象組的maxLifeTime,則所述內(nèi)存對(duì)象組的maxLifeTime不作改變,且stableTime隨著被釋放內(nèi)存的CPU處理時(shí)間而增力口,否則,對(duì)maxLifeTime進(jìn)行更新,且將stableTime重置為O。在本發(fā)明一實(shí)施例中,檢測(cè)潛在的內(nèi)存泄漏的方法為定義在程序所有可能的執(zhí)行路徑上都不會(huì)釋放的內(nèi)存對(duì)象為總是泄漏內(nèi)存對(duì)象ALeak;定義在程序有些執(zhí)行路徑上會(huì)釋放分配,但在程序其他路徑上不會(huì)釋放分配的內(nèi)存對(duì)象為有時(shí)泄漏內(nèi)存對(duì)象SLeak;根據(jù)內(nèi)存對(duì)象的分組,針對(duì)ALeak、SLeak兩種不同的泄漏類型,分別采用如下的方法進(jìn)行檢測(cè)檢測(cè)ALeak包括以下步驟步驟2.1:檢測(cè)每一個(gè)內(nèi)存對(duì)象組中活內(nèi)存對(duì)象的數(shù)量是否超過了預(yù)設(shè)的閾值,是則轉(zhuǎn)至步驟2.2,進(jìn)一步檢查該內(nèi)存對(duì)象組使用的內(nèi)存是否連續(xù)增長,否則轉(zhuǎn)至步驟2.3;步驟2.2:如果該內(nèi)存對(duì)象組的最后分配時(shí)間離當(dāng)前時(shí)間較近,內(nèi)存使用仍在增長,則該內(nèi)存對(duì)象組是泄漏嫌疑對(duì)象;如果最后分配時(shí)間離當(dāng)前時(shí)間較遠(yuǎn),即在一段較長時(shí)間內(nèi)都沒有內(nèi)存使用增長,則不會(huì)發(fā)生內(nèi)存泄漏;步驟2.3:如果沒有超過,則可能是在初始時(shí)程序分配了較多內(nèi)存對(duì)象,在整個(gè)執(zhí)行過程中這些對(duì)象都在使用;檢測(cè)SLeak的方法為檢測(cè)每一個(gè)內(nèi)存對(duì)象組中活內(nèi)存對(duì)象的生命期lifeTime,如果所述活內(nèi)存對(duì)象的活動(dòng)時(shí)間超過所在內(nèi)存對(duì)象組的maxLifeTime的兩倍,且??,且所述活內(nèi)存對(duì)象在合法的maxLifeTime內(nèi)動(dòng)態(tài)內(nèi)存部分不釋放,但持續(xù)申請(qǐng),導(dǎo)致所占用的內(nèi)存越來越多,且所述活內(nèi)存對(duì)象在合法的maxLifeTime內(nèi)已釋放,但多次重復(fù)釋放,導(dǎo)致不可預(yù)計(jì)的行為發(fā)生,則判斷所述內(nèi)存對(duì)象組是泄漏嫌疑對(duì)象。在本發(fā)明一實(shí)施例中,判定內(nèi)存泄漏的方法為步驟3.1:對(duì)于在檢測(cè)過程中已標(biāo)記為泄漏嫌疑對(duì)象的內(nèi)存對(duì)象,在預(yù)定的時(shí)間閾值內(nèi),如果所述內(nèi)存對(duì)象被再次訪問,則所述內(nèi)存對(duì)象為可能泄漏內(nèi)存對(duì)象PLeak,否則所述內(nèi)存對(duì)象確定為泄漏對(duì)象;步驟3.2:如果內(nèi)存對(duì)象為PLeak,則重置這個(gè)內(nèi)存對(duì)象的分配時(shí)間為當(dāng)前時(shí)間;如果這個(gè)內(nèi)存對(duì)象重新變?yōu)樾孤┫右蓪?duì)象,則確認(rèn)該內(nèi)存對(duì)象為泄漏對(duì)象。本發(fā)明還提供了一種面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法的實(shí)現(xiàn)系統(tǒng),包括Xen內(nèi)部緩沖區(qū)維護(hù)模塊、控制模塊、攔截模塊和監(jiān)視模塊。在本發(fā)明一實(shí)施例中,所述Xen內(nèi)部緩沖區(qū)維護(hù)模塊定義了若干個(gè)有關(guān)的超級(jí)調(diào)用來輔助完成對(duì)內(nèi)存相關(guān)操作的捕捉,并獲到相關(guān)數(shù)據(jù),用于泄漏對(duì)象分組和判定。在本發(fā)明一實(shí)施例中,所述控制模塊用以控制被測(cè)進(jìn)程,使被測(cè)進(jìn)程主動(dòng)加載攔截模塊,并向攔截模塊發(fā)送指令,使攔截模塊能對(duì)被測(cè)進(jìn)程進(jìn)行修改,攔截被測(cè)進(jìn)程內(nèi)存的申請(qǐng)和釋放操作。在本發(fā)明一實(shí)施例中,所述攔截模塊對(duì)被測(cè)進(jìn)程內(nèi)存的申請(qǐng)和釋放操作進(jìn)行攔截,并通過超級(jí)調(diào)用將攔截到的數(shù)據(jù)傳送到Xen內(nèi)部緩沖區(qū)維護(hù)模塊,等待進(jìn)一步處理。在本發(fā)明一實(shí)施例中,所述監(jiān)視模塊與攔截模塊協(xié)同作用,攔截模塊負(fù)責(zé)攔截內(nèi)存操作行為,監(jiān)視模塊對(duì)攔截到的行為進(jìn)行處理,包括分組確認(rèn)泄漏對(duì)象和可視化處理。與現(xiàn)有技術(shù)相比,本發(fā)明的有益效果是1、跨平臺(tái)性。不僅適用于GNU/Linux操作系統(tǒng),而且對(duì)Windows也適用,不僅適用于用戶程序,對(duì)操作系統(tǒng)內(nèi)核也同樣適用。2、動(dòng)態(tài)性。能夠在程序運(yùn)行時(shí)對(duì)內(nèi)存泄漏進(jìn)行檢測(cè),能夠在長時(shí)間不間斷運(yùn)行的系統(tǒng)中使用,而且效率并不會(huì)降低太多。3、透明性。本發(fā)明只需要對(duì)支撐虛擬機(jī)運(yùn)行的虛擬機(jī)管理器進(jìn)行修改,通過提供超級(jí)調(diào)用,對(duì)內(nèi)存泄漏進(jìn)行了有效地檢測(cè),不需要修改現(xiàn)有的操作系統(tǒng),也無需修改被檢測(cè)程序的代碼,對(duì)被測(cè)程序是透明的。4、有效性。本發(fā)明在公認(rèn)的存在內(nèi)存泄漏的開源項(xiàng)目中能有效的檢測(cè)出運(yùn)行時(shí)的內(nèi)存泄漏。圖1為本發(fā)明基于Xen平臺(tái)的VMLD體系結(jié)構(gòu)圖。圖2為本發(fā)明在Xen虛擬計(jì)算環(huán)境中部署的自定義超級(jí)調(diào)用示意圖。圖3為本發(fā)明的超級(jí)調(diào)用StartWrite不可重入情況的流程圖。圖4為本發(fā)明的超級(jí)調(diào)用StartWrite可重入情況的流程圖。圖5為本發(fā)明監(jiān)視開始后被測(cè)進(jìn)程中malloc的調(diào)用流程圖。圖6為本發(fā)明面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法的流程圖。具體實(shí)施例方式本發(fā)明面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法,如圖6所示,包括以下步驟步驟1:動(dòng)態(tài)分析受監(jiān)控程序的內(nèi)存使用行為,根據(jù)內(nèi)存對(duì)象所屬事件的不同或其它分組原則對(duì)內(nèi)存對(duì)象進(jìn)行分組,形成多個(gè)內(nèi)存對(duì)象組,并對(duì)各內(nèi)存對(duì)象組相關(guān)信息進(jìn)行維護(hù)和更新;所述內(nèi)存對(duì)象是指經(jīng)系統(tǒng)調(diào)用如malloc、realloc、calloc等分配的內(nèi)存塊;所述內(nèi)存對(duì)象生命期是指內(nèi)存對(duì)象從被分配到被釋放的這段時(shí)間,所述內(nèi)存對(duì)象生命期的取值在一個(gè)數(shù)學(xué)意義上的開區(qū)間(0,內(nèi);所述內(nèi)存對(duì)象組是指具有某種共性的內(nèi)存對(duì)象的集合,每個(gè)內(nèi)存對(duì)象都采用一個(gè)元組(size,callChain)來表示,size表示內(nèi)存對(duì)象的大小,callChain表示在分配內(nèi)存對(duì)象時(shí)的棧調(diào)用(call_stack);步驟2:基于觀測(cè)到的行為特征檢測(cè)潛在的內(nèi)存泄漏;步驟3:依據(jù)相關(guān)規(guī)則進(jìn)行內(nèi)存泄漏判定。在步驟I中,動(dòng)態(tài)分析受監(jiān)控程序的內(nèi)存使用行為,對(duì)各內(nèi)存對(duì)象組相關(guān)信息進(jìn)行維護(hù)和更新的方法為步驟1.1:對(duì)于每一個(gè)內(nèi)存對(duì)象組,對(duì)其內(nèi)存分配與釋放的行為實(shí)施收集,記錄相關(guān)信息,包括生命期信息、內(nèi)存使用信息;所述生命期信息包括內(nèi)存對(duì)象組的最大生命期maxLifeTime、最大生命期的穩(wěn)定時(shí)間stableTime,所有的時(shí)間都以CPU時(shí)間來度量;所述內(nèi)存使用信息包括內(nèi)存對(duì)象組內(nèi)的活內(nèi)存對(duì)象信息、最后分配時(shí)間、內(nèi)存對(duì)象組占用的總內(nèi)存空間大?。徊襟E1.2:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一個(gè)活內(nèi)存對(duì)象,記錄其內(nèi)存分配時(shí)間,同一個(gè)內(nèi)存對(duì)象組內(nèi)所有活內(nèi)存對(duì)象都以雙向鏈表的形式表示,以便快速查找;步驟1.3:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一次內(nèi)存分配,即一個(gè)新的活內(nèi)存對(duì)象添加到所述雙向鏈表后,對(duì)內(nèi)存對(duì)象組的關(guān)聯(lián)信息進(jìn)行更新,包括活內(nèi)存對(duì)象信息、最后分配時(shí)間、內(nèi)存對(duì)象組占用的總內(nèi)存空間大小等等;步驟1.4:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一次內(nèi)存釋放,也對(duì)內(nèi)存對(duì)象組的關(guān)聯(lián)信息進(jìn)行相應(yīng)的更新,包括活內(nèi)存對(duì)象信息、內(nèi)存對(duì)象組占用的總空間大小等等,同時(shí)通過計(jì)算被釋放內(nèi)存的分配時(shí)間與當(dāng)前時(shí)間的差值,求得被釋放內(nèi)存的生命期lifeTime;步驟1.5:如果被釋放內(nèi)存的IifeTime少于所在內(nèi)存對(duì)象組的maxLifeTime,則所述內(nèi)存對(duì)象組的maxLifeTime不作改變,且stableTime隨著被釋放內(nèi)存的CPU處理時(shí)間而增力口,否則,對(duì)maxLifeTime進(jìn)行更新,且將stableTime重置為O。步驟1.6:在這個(gè)過程中,涉及到mallocO、callocO、reallocO、free0等內(nèi)存調(diào)用函數(shù),統(tǒng)一稱之為內(nèi)存分配(allocation)與釋放(deallocation),或僅以mallocO、freeO表達(dá)。在步驟2中,檢測(cè)潛在的內(nèi)存泄漏的方法為定義在程序所有可能的執(zhí)行路徑上都不會(huì)釋放的內(nèi)存對(duì)象為總是泄漏內(nèi)存對(duì)象ALeak;定義在程序有些執(zhí)行路徑上會(huì)釋放分配,但在程序其他路徑上不會(huì)釋放分配的內(nèi)存對(duì)象為有時(shí)泄漏內(nèi)存對(duì)象SIeak;根據(jù)內(nèi)存對(duì)象的分組,針對(duì)Aleak、SIeak兩種不同的泄漏類型,分別采用如下的方法進(jìn)行檢測(cè)檢測(cè)Aleak包括以下步驟步驟2.1:檢測(cè)每一個(gè)內(nèi)存對(duì)象組中活內(nèi)存對(duì)象的數(shù)量是否超過了預(yù)設(shè)的閾值,是則轉(zhuǎn)至步驟2.2,進(jìn)一步檢查該內(nèi)存對(duì)象組使用的內(nèi)存是否連續(xù)增長,否則轉(zhuǎn)至步驟2.3;步驟2.2:如果該內(nèi)存對(duì)象組的最后分配時(shí)間離當(dāng)前時(shí)間較近,內(nèi)存使用仍在增長,則該內(nèi)存對(duì)象組是泄漏嫌疑對(duì)象;如果最后分配時(shí)間離當(dāng)前時(shí)間較遠(yuǎn),即在一段較長時(shí)間內(nèi)都沒有內(nèi)存使用增長,則不會(huì)發(fā)生內(nèi)存泄漏;步驟2.3:如果沒有超過,則可能是在初始時(shí)程序分配了較多內(nèi)存對(duì)象,在整個(gè)執(zhí)行過程中這些對(duì)象都在使用;檢測(cè)Sleak的方法為檢測(cè)每一個(gè)內(nèi)存對(duì)象組中活內(nèi)存對(duì)象的生命期lifeTime,如果所述活內(nèi)存對(duì)象的活動(dòng)時(shí)間超過所在內(nèi)存對(duì)象組的maxLifeTime的兩倍,且??,且所述活內(nèi)存對(duì)象在合法的maxLifeTime內(nèi)動(dòng)態(tài)內(nèi)存部分不釋放,但持續(xù)申請(qǐng),導(dǎo)致所占用的內(nèi)存越來越多,且所述活內(nèi)存對(duì)象在合法的maxLifeTime內(nèi)已釋放,但多次重復(fù)釋放,導(dǎo)致不可預(yù)計(jì)的行為發(fā)生,則判斷所述內(nèi)存對(duì)象組是泄漏嫌疑對(duì)象。以上兩種情況的檢測(cè),都只是在程序運(yùn)行過程中有內(nèi)存申請(qǐng)與釋放行為時(shí)才觸發(fā)這個(gè)檢測(cè)過程,而且這個(gè)檢測(cè)只是在一個(gè)預(yù)設(shè)的檢測(cè)周期內(nèi)進(jìn)行,因而所占用的內(nèi)存開銷不大。在步驟3中,判定內(nèi)存泄漏的方法為步驟3.1:對(duì)于在檢測(cè)過程中已標(biāo)記為泄漏嫌疑對(duì)象的內(nèi)存對(duì)象,在預(yù)定的時(shí)間閾值內(nèi),如果所述內(nèi)存對(duì)象被再次訪問,則所述內(nèi)存對(duì)象為可能泄漏內(nèi)存對(duì)象PLeak,否則所述內(nèi)存對(duì)象確定為泄漏對(duì)象;步驟3.2:如果內(nèi)存對(duì)象為Pleak,則重置這個(gè)內(nèi)存對(duì)象的分配時(shí)間為當(dāng)前時(shí)間;如果這個(gè)內(nèi)存對(duì)象重新變?yōu)樾孤┫右蓪?duì)象,則確認(rèn)該內(nèi)存對(duì)象為泄漏對(duì)象。以上判定過程并沒有占用很大的額外開銷,僅僅是對(duì)少數(shù)嫌疑泄漏對(duì)象進(jìn)行確認(rèn),因此程序的運(yùn)行性能并不會(huì)受到大的影響。下面結(jié)合具體實(shí)施例對(duì)本發(fā)明面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法的實(shí)現(xiàn)系統(tǒng)進(jìn)行說明。本發(fā)明的實(shí)現(xiàn)是基于開源的虛擬機(jī)管理器Xen來完成的。我們分別在虛擬機(jī)內(nèi)進(jìn)行監(jiān)控,在虛擬機(jī)管理器內(nèi)確認(rèn)內(nèi)存泄漏。不同于已有的方法,不僅適用于GNU/Linux操作系統(tǒng),而且對(duì)Windows也適用,不僅適用于用戶程序,對(duì)操作系統(tǒng)內(nèi)核也同樣適用,從而可以實(shí)現(xiàn)真正跨平臺(tái)的檢測(cè)運(yùn)行時(shí)內(nèi)存泄漏。同時(shí)實(shí)現(xiàn)方法簡單,該方法不需要修改現(xiàn)有的操作系統(tǒng),只需對(duì)支撐虛擬機(jī)運(yùn)行的虛擬機(jī)管理器進(jìn)行修改,通過編制虛擬機(jī)管理器環(huán)境下的超級(jí)調(diào)用來實(shí)現(xiàn)對(duì)內(nèi)存泄漏對(duì)象的檢測(cè)、標(biāo)識(shí)可能的泄漏嫌疑對(duì)象,并進(jìn)行虛擬管理器環(huán)境下的泄漏確認(rèn)。本實(shí)施例在`以下實(shí)驗(yàn)環(huán)境中完成=IntelHM61,雙核酷睿二代i3處理器(i3-2120CPU),3.3GHz,3MBCache,2GB內(nèi)存。Xen4·1.2版本,Linux內(nèi)核版本Fedora16Linux-3.1.0-7.fcl6.686.PAE,CentOS6,所用編譯器GCC的版本4.4.6,SATA串行硬盤。因?yàn)閄en支持全虛擬化,我們將相關(guān)工作定位在硬件虛擬域HVM上,在Xen虛擬機(jī)管理器VMM系統(tǒng)中存在一個(gè)輕量級(jí)的軟件層,向之上的虛擬機(jī)提供虛擬硬件資源,同時(shí)分配和管理這些資源,并保證虛擬機(jī)之間的相互隔離。在Xen系統(tǒng)中,VMM又稱為XenHypervisor,簡稱為Xen,而虛擬機(jī)則被稱為虛擬域(Domain),每一個(gè)Domain用來安裝客戶操作系統(tǒng)(GuestOS),由Xen控制,以高效的利用CPU的物理資源。每個(gè)客戶操作系統(tǒng)可以管理它自身的應(yīng)用。這種管理包括每個(gè)程序在規(guī)定時(shí)間內(nèi)的響應(yīng)到執(zhí)行,是通過Xen調(diào)度到虛擬機(jī)中實(shí)現(xiàn)。特權(quán)域DomainO(Dom0)用來輔助VMM管理其他虛擬域,是其它虛擬主機(jī)的管理者和控制者。Xen向HVM及DomU提供了管理和虛擬硬件的API抽象層,使DomO擁有真實(shí)的設(shè)備驅(qū)動(dòng)區(qū)(原生設(shè)備驅(qū)動(dòng),nativedevicedriver),能夠直接訪問物理硬件,它負(fù)責(zé)與Xen提供的管理工作API交互,可以管理和控制其他域。如圖1所示,本發(fā)明面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法的實(shí)現(xiàn)系統(tǒng)由4個(gè)功能模塊組成,包括Xen內(nèi)部緩沖區(qū)維護(hù)模塊、控制模塊、攔截模塊和監(jiān)視模塊。在被監(jiān)控端,被測(cè)進(jìn)程是未經(jīng)修改的正在運(yùn)行的一個(gè)進(jìn)程。如圖2,所述Xen內(nèi)部緩沖區(qū)維護(hù)模塊定義了若干個(gè)有關(guān)的超級(jí)調(diào)用來輔助完成對(duì)內(nèi)存相關(guān)操作的捕捉,并獲到相關(guān)數(shù)據(jù),用于泄漏對(duì)象分組和判定。所述控制模塊用以控制被測(cè)進(jìn)程,使被測(cè)進(jìn)程主動(dòng)加載攔截模塊,并向攔截模塊發(fā)送指令,使攔截模塊能對(duì)被測(cè)進(jìn)程進(jìn)行修改,攔截被測(cè)進(jìn)程內(nèi)存的申請(qǐng)和釋放操作;所述控制模塊能夠動(dòng)態(tài)地控制攔截模塊的啟動(dòng)與停止,而不需要重啟被測(cè)進(jìn)程等操作,以便整個(gè)檢測(cè)過程不會(huì)對(duì)被測(cè)進(jìn)程提供的服務(wù)造成負(fù)面影響。所述攔截模塊對(duì)被測(cè)進(jìn)程內(nèi)存的申請(qǐng)和釋放操作進(jìn)行攔截,并通過超級(jí)調(diào)用將攔截到的數(shù)據(jù)傳送到Xen內(nèi)部緩沖區(qū)維護(hù)模塊,等待進(jìn)一步處理。所述監(jiān)視模塊與攔截模塊協(xié)同作用,攔截模塊負(fù)責(zé)攔截內(nèi)存操作行為,監(jiān)視模塊對(duì)攔截到的行為進(jìn)行處理,包括分組確認(rèn)泄漏對(duì)象和可視化處理。由于Xen提供的服務(wù)并不是和操作系統(tǒng)直接相關(guān)的,遇到超級(jí)調(diào)用的時(shí),無論是Windows系統(tǒng)還是Linux系統(tǒng),都能直接返回Xen。利用這個(gè)特性,可以屏蔽掉軟件實(shí)現(xiàn)的一些系統(tǒng)相關(guān)的細(xì)節(jié),以便用更加統(tǒng)一的策略來完成內(nèi)存申請(qǐng)和釋放的攔截。下面進(jìn)一步闡述上述各個(gè)模塊的實(shí)現(xiàn)方法。l、Xen內(nèi)部緩沖區(qū)維護(hù)模塊自定義6個(gè)有關(guān)的超級(jí)調(diào)用來輔助完成對(duì)內(nèi)存相關(guān)操作的捕捉,并獲到有關(guān)的數(shù)據(jù)(l)intenvTestO:調(diào)用號(hào)為0x100。功能是檢測(cè)運(yùn)行環(huán)境,是否是修改過的Xen內(nèi)核,運(yùn)行環(huán)境中是否包含這些自定義的超級(jí)調(diào)用。如果是,則返回0x12345678,否則就不是。具體實(shí)現(xiàn)形式如;regs_>eax=0x12345678。(2)voidclearO:調(diào)用號(hào)為0x102,作用是重置key,重置緩沖區(qū)鎖定狀態(tài),清空緩沖區(qū)。在Xen添加的代碼中,維護(hù)著一些數(shù)據(jù)。主要用于標(biāo)志當(dāng)前有權(quán)限的寫入者的CurrentKey、分配給寫入者權(quán)限的Key、保存寫入數(shù)據(jù)的Buffer、用來標(biāo)識(shí)當(dāng)前Buffer使用狀態(tài)的ReadPos與WritePos。clear的作用就是把以上數(shù)據(jù)全部置O。(3)intstartffrite():調(diào)用號(hào)為0x103。功能是向Xen內(nèi)核申請(qǐng)緩沖區(qū)的寫入。為防止多個(gè)寫入者同時(shí)訪問緩沖區(qū)出現(xiàn)寫沖突,破壞數(shù)據(jù)暫存緩沖區(qū)的一致性。具體的方法是,寫入者在需要寫入數(shù)據(jù)之前,先向修改過的Xen內(nèi)核通過超級(jí)調(diào)用申請(qǐng)一個(gè)寫入key,這個(gè)寫入key作為有權(quán)限向暫存緩沖區(qū)寫入數(shù)據(jù)的證明。拿到了有效的key以后,就可以開始向緩沖區(qū)內(nèi)寫入數(shù)據(jù)。在寫入完畢后,釋放所獲取的key,釋放之后key即失效。在這個(gè)操作中,涉及到了共享的變量“當(dāng)前有寫入權(quán)限的key”。若不考慮key獲取函數(shù)的可重入性,則可能會(huì)出現(xiàn)多個(gè)寫者同時(shí)進(jìn)行數(shù)據(jù)寫入的情況。在圖3中,最后兩邊都返回了key,是錯(cuò)誤的。利用Intelx86/64架構(gòu)CPU提供的指令,可以實(shí)現(xiàn)加鎖的原子操作,重新設(shè)計(jì)后,得到流程圖4。所以利用LOCK前綴和CMPXCHG指令,可以實(shí)現(xiàn)比較并賦值的原子操作。若返回值非0,則獲取到了對(duì)Xen內(nèi)緩沖區(qū)的寫入權(quán)限。(4)voidendffrite(intkey):調(diào)用號(hào)為0x105。功能是結(jié)束寫入操作,釋放key。該操作中,也涉及到比較與賦值的問題,故同StartWrite調(diào)用類似,使用了LOCK和CMPXCHG指令實(shí)現(xiàn)原子操作比較參數(shù)中的key是不是當(dāng)前有寫入權(quán)限的key,如果是則把當(dāng)前有權(quán)限寫入的key設(shè)置為O(未使用),否則返回失敗。(5)intsend(intkey,void*buf,intlen):調(diào)用號(hào)為0x104。功能是向Xen的暫存緩沖區(qū)寫入數(shù)據(jù),返回O代表寫入失敗,I代表寫入成功。如果要求寫入的數(shù)據(jù)超過Xen緩沖區(qū)的空閑大小,則寫入失敗。(6)intrecv(void*buf,intlen):調(diào)用號(hào)為0x106。功能是從Xen讀取數(shù)據(jù),返回讀取的字節(jié)數(shù)。2、控制模塊在被檢測(cè)程序運(yùn)行時(shí),控制模塊可以單獨(dú)運(yùn)行,在虛擬機(jī)內(nèi)部對(duì)被測(cè)進(jìn)程進(jìn)行控制。它可以將攔截模塊動(dòng)態(tài)地載入到運(yùn)行中的被測(cè)進(jìn)程里,使得攔截被測(cè)進(jìn)程中內(nèi)存的申請(qǐng)與釋放操作變?yōu)榭赡堋T诎褦r截模塊動(dòng)態(tài)載入內(nèi)存之后,它能夠動(dòng)態(tài)地控制攔截模塊的啟動(dòng)與停止,且不需要重啟進(jìn)程等操作,實(shí)現(xiàn)整個(gè)檢測(cè)過程中不影響被檢測(cè)進(jìn)程繼續(xù)提供服務(wù)。要對(duì)一個(gè)進(jìn)程的內(nèi)存空間的數(shù)據(jù)進(jìn)行讀寫訪問,需要通過操作系統(tǒng)提供的系統(tǒng)調(diào)用來實(shí)現(xiàn)。在Windows下,可以使用DebugActiveProcess、WaitForDebugEvent>Get/SetThreadContext和Write/ReadProcessMemory等函數(shù)對(duì)運(yùn)行中的進(jìn)程進(jìn)行調(diào)試控制。在Linux下,可以通過ptrace函數(shù)對(duì)運(yùn)行中的進(jìn)程進(jìn)行調(diào)試控制。許多在x86構(gòu)架上運(yùn)行的程序,函數(shù)調(diào)用的時(shí)候使用了cdecl調(diào)用約定。該調(diào)用約定將參數(shù)從右到左壓入堆棧,在函數(shù)返回的時(shí)候?qū)⒎祷刂当4嬖贓AX寄存器中,參數(shù)出棧由主調(diào)者完成,函數(shù)調(diào)用過程中,EAX、ECX、EDX寄存器的值不需要進(jìn)行保留。cdecl調(diào)用約定屬于應(yīng)用程序二進(jìn)制接口(ApplicationBinaryInterface)的一部分。在x86的程序執(zhí)行環(huán)境中,需要關(guān)注的幾個(gè)寄存器有EIP、ESP、EAX。EIP寄存器是指令指針,它保存的是下一條需要執(zhí)行的指令在內(nèi)存中的位置,要執(zhí)行某個(gè)函數(shù)的代碼,只要把EIP指向該函數(shù)的入口即可。ESP寄存器指向當(dāng)前執(zhí)行環(huán)境中堆棧的頂端在內(nèi)存中的位置。前面提到,x86上cdecl調(diào)用約定首先是將參數(shù)壓入堆棧的,那么就可以通過直接操縱堆棧的方式,來寫入自己想要的參數(shù)。然后是函數(shù)調(diào)用,函數(shù)調(diào)用的時(shí)候,用CALL語句改變EIP寄存器的值。CALL有好幾種nearcall、farcalI>inter-privilegefarcall、taskswitch。Windows或Linux中調(diào)用C語言運(yùn)行庫的內(nèi)存申請(qǐng)釋放函數(shù)的時(shí)候用的是nearcall。可以看出,整個(gè)調(diào)用過程,是將EIP壓入棧,然后將EIP設(shè)置為目標(biāo)地址。由于之前所述,堆??梢酝ㄟ^更改ESP寄存器和內(nèi)存直接進(jìn)行控制,EIP寄存器在調(diào)試器權(quán)限下也可以更改(屬于線程上下文)。故可以通過調(diào)試器控制進(jìn)程進(jìn)行函數(shù)調(diào)用。函數(shù)調(diào)用結(jié)束后會(huì)執(zhí)行RET語句返回。由上可知,函數(shù)返回的時(shí)候,會(huì)從棧頂取出一個(gè)元素,作為新的EIP。在由調(diào)試器控制函數(shù)調(diào)用的情況下,如果函數(shù)返回之后立即恢復(fù)執(zhí)行原有代碼,那么會(huì)很難判斷函數(shù)什么時(shí)候調(diào)用完畢,以進(jìn)行進(jìn)一步控制。于是就在調(diào)整為函數(shù)調(diào)用時(shí)剛到函數(shù)入口時(shí)的狀態(tài)的時(shí)候,將O壓入棧頂作為最后的返回值,這樣在函數(shù)執(zhí)行完畢后EIP會(huì)變?yōu)?,產(chǎn)生異常,由調(diào)試器捕捉到,此時(shí)便可以進(jìn)行進(jìn)一步控制。3、攔截模塊攔截模塊負(fù)責(zé)將C語言運(yùn)行支持庫(runtime)中的malloc函數(shù)和free函數(shù)進(jìn)行重定向。在C語言中,堆上內(nèi)存的分配與釋放分別對(duì)應(yīng)這兩個(gè)函數(shù),如果接管了這兩個(gè)函數(shù),也就對(duì)堆上內(nèi)存的分配和釋放行為發(fā)生的時(shí)候能夠進(jìn)行控制了。攔截模塊在使用時(shí)以共享函數(shù)庫的身份,借助控制模塊載入到被測(cè)進(jìn)程中。攔截模塊負(fù)責(zé)從進(jìn)程內(nèi)部攔截內(nèi)存的申請(qǐng)和釋放操作。它查找進(jìn)程已載入的模塊的符號(hào),找到malloc和free后,獲取這兩個(gè)函數(shù)的入口地址,隨后將這兩個(gè)函數(shù)的入口重定向到自己的替代代碼中。在替代代碼里,它記錄這次函數(shù)的調(diào)用行為、返回值等信息,然后將信息通過超級(jí)調(diào)用傳遞給Xen。它也可以在控制模塊的操縱下,對(duì)函數(shù)的重定向進(jìn)行取消,停止對(duì)內(nèi)存申請(qǐng)和釋放的監(jiān)控。實(shí)現(xiàn)攔截模塊的關(guān)鍵點(diǎn)在于能夠?qū)σ呀?jīng)編譯成機(jī)器代碼并加載到內(nèi)存中的進(jìn)程進(jìn)行修改,從而接管malloc和free函數(shù)。在代碼還未進(jìn)行編譯的時(shí)候,可以通過定義一個(gè)宏,將malloc和free替換成自己的函數(shù)名,從而使代碼在預(yù)處理的時(shí)候所有malloc和free就被替換。在程序運(yùn)行的時(shí)候,這些代碼已經(jīng)被載入內(nèi)存。如果需要修改內(nèi)存中的這些代碼,在malloc和free的函數(shù)開頭可以加上一個(gè)類似C語言goto語句的指令,那么就可以跳轉(zhuǎn)到自定義函數(shù)中。類似goto語句的機(jī)器代碼就是0xe9,對(duì)應(yīng)的匯編指令是JMP,具體的指令形式為JMPrel320整個(gè)指令占用5個(gè)字節(jié),因此,需要覆蓋原函數(shù)開頭的5個(gè)字節(jié)才能順利將這條指令寫入。而rel32占用4個(gè)字節(jié),也就是說,若自己的代碼(替代函數(shù))所在的內(nèi)存地址為F2,要攔截的函數(shù)(比如malloc)所在的內(nèi)存地址為F1,那么立即數(shù)rel32的值就是rel32=F2_Fl+5。雖然在原函數(shù)的開頭加入了JMP語句,但是原函數(shù)并不能因此而廢棄,因?yàn)樯暾?qǐng)內(nèi)存最終還是要調(diào)用原malloc,釋放內(nèi)存還是要調(diào)用原free。由于原函數(shù)入口已經(jīng)被破壞(原有代碼被JMP覆蓋),故原函數(shù)事實(shí)上已經(jīng)處于不可用狀態(tài)。所以在覆蓋原函數(shù)起始處代碼的時(shí)候,需要考慮這個(gè)函數(shù)的調(diào)用問題。解決的思路如下。因?yàn)樵瘮?shù)只有入口處的幾條機(jī)器代碼被覆蓋,所以只要讓CPU先執(zhí)行被破壞的這幾條指令,然后接著從沒有被覆蓋的指令執(zhí)行下去,就可以正確調(diào)用這些函數(shù)。故在覆蓋原函數(shù)入口的時(shí)候,先將那些代碼備份到其他地方,然后在備份的代碼末尾加上JMP語句跳回原函數(shù)未被破壞的部分,調(diào)用的時(shí)候直接朝著備份的地方調(diào)用,問題就可以解決。復(fù)制機(jī)器代碼需要了解被復(fù)制的代碼是不是可以直接復(fù)制并被使用的。因?yàn)橐牡暮瘮?shù)入口只有5個(gè)字節(jié),所以要復(fù)制的代碼只要滿足能騰出5個(gè)字節(jié)的空間即可。必須要解決以下問題代碼的長度未知、代碼是否可以直接復(fù)制、代碼運(yùn)行的結(jié)果是否不變。下面對(duì)這3個(gè)問題分別加以解決。第一個(gè)問題可以通過一個(gè)反匯編器來進(jìn)行機(jī)器代碼的分析,以解決問題。獲得代碼長度是反匯編器最基本的功能,知道了代碼長度,就知道了有多少代碼要復(fù)制(因?yàn)椴⒉豢偸钦?個(gè)字節(jié)),知道了跳轉(zhuǎn)回來的時(shí)候應(yīng)該跳轉(zhuǎn)到什么地址。這里選用的反匯編器是C語言版本的HDE32。第二個(gè)問題,主要涉及到JMP、CALL等立即數(shù)為相對(duì)地址的指令。使用HDE32進(jìn)行代碼分析之后,可以得知操作數(shù)是不是立即數(shù),如果是立即數(shù)那么是不是相對(duì)地址。如果是相對(duì)地址,那么根據(jù)原指令所在地址和相對(duì)地址得到該指令引用的實(shí)際地址(絕對(duì)地址),然后根據(jù)將要存放該指令的目標(biāo)地址和引用的實(shí)際地址計(jì)算出立即數(shù)應(yīng)該是多少。這一步是指令復(fù)制時(shí)的修正。第三個(gè)問題,對(duì)于進(jìn)行函數(shù)調(diào)用的CALL指令,正常情況下遇上使用相對(duì)地址立即數(shù)的,修正立即數(shù)即可解決問題。但是有一類函數(shù)比較特殊,它們會(huì)用到調(diào)用函數(shù)時(shí)壓入棧里的返回地址。例如在glibc的free函數(shù)中,前5個(gè)字節(jié)就遇上了這樣的函數(shù)調(diào)用,以實(shí)現(xiàn)共享函數(shù)庫能夠與模塊載入位置無關(guān)(例如是靜態(tài)變量、全局變量等資源的引用)而正常運(yùn)行。但是將這樣的CALL語句復(fù)制到別處以后,執(zhí)行結(jié)果就和復(fù)制之前不同(因?yàn)閷?shí)質(zhì)上獲取的是CALL語句的下一句的地址)。這個(gè)問題通過模擬CALL語句來實(shí)現(xiàn),根據(jù)CALL語句的行為,包含一個(gè)壓棧和一個(gè)跳轉(zhuǎn),那么用一個(gè)I3USH語句和一個(gè)JMP語句替換原有的CALL語句,即可達(dá)到目的。因?yàn)橐粭lCALL語句的長度已經(jīng)足夠5個(gè)字節(jié),故覆蓋CALL語句之后,也不用擔(dān)心函數(shù)調(diào)用返回的時(shí)候自己新增的代碼失去控制權(quán)的問題,因?yàn)镃ALL語句之后不用再有需要執(zhí)行的代碼了,可以接下去執(zhí)行原函數(shù)中未被破壞的部分。如圖5展示了監(jiān)視開始后被測(cè)進(jìn)程中malloc的調(diào)用流程。整個(gè)過程都是動(dòng)態(tài)完成的,操作對(duì)進(jìn)程透明,使用之前不需要對(duì)進(jìn)程進(jìn)行特別的處理。如果在攔截到內(nèi)存申請(qǐng)、釋放操作的時(shí)候進(jìn)入ringO然后再進(jìn)行超級(jí)調(diào)用,那么頻繁的ring3與ringO之間的切換會(huì)導(dǎo)致性能很大的下降。因此,若對(duì)Xen現(xiàn)有機(jī)制進(jìn)行一些修改,使得該工具的攔截模塊能直接從用戶態(tài)向Xen傳遞數(shù)據(jù),可以得到一定性能上的提升。Xen原本提供的超級(jí)調(diào)用限制較多,如果在用戶態(tài)進(jìn)行超級(jí)調(diào)用的話,則調(diào)用會(huì)失敗。故對(duì)Xen修改的時(shí)候,可直接將新增的超級(jí)調(diào)用加入檢測(cè)虛擬機(jī)是不是處于內(nèi)核態(tài)的代碼之前,從而跳過Xen的檢測(cè)。4、監(jiān)視模塊監(jiān)視模塊和攔截模塊協(xié)同作用,對(duì)被測(cè)進(jìn)程中的堆內(nèi)存申請(qǐng)和釋放行為進(jìn)行監(jiān)視。攔截模塊負(fù)責(zé)攔截malloc和free等調(diào)用行為,監(jiān)視模塊則對(duì)攔截到的這些行為進(jìn)行處理。如果用設(shè)計(jì)模式中的觀察者模式進(jìn)行解釋的話,被測(cè)進(jìn)程就是被觀察的目標(biāo),而攔截模塊就是觀察者,并且僅僅觀察,并不行動(dòng)。具體對(duì)觀察到的行為作出響應(yīng)的則是監(jiān)視模塊。監(jiān)視模塊主要是獲取調(diào)用時(shí)的參數(shù)以及函數(shù)返回值等信息,其中原函數(shù)的調(diào)用由攔截模塊負(fù)責(zé)。在攔截模塊修改了malloc和free的函數(shù)入口以后,調(diào)用malloc和free就被重定向到監(jiān)視模塊中。此時(shí)可以直接通過讀取棧中的地址,得知程序要申請(qǐng)多大的內(nèi)存空間或者釋放哪里的內(nèi)存空間。讀取部分可以直接通過編寫匯編語言實(shí)現(xiàn),當(dāng)然更簡單的方法是自己編寫一個(gè)具有同樣聲明的函數(shù),這樣對(duì)于被測(cè)進(jìn)程來說,調(diào)用malloc就相當(dāng)于直接調(diào)用監(jiān)視模塊中的相關(guān)函數(shù),于是獲取參數(shù)的方式就變得和編寫C語言代碼時(shí)完全一樣直接訪問形參。監(jiān)視模塊只負(fù)責(zé)接收消息,將消息以XML的格式輸出,這樣它的接口靈活,方便各種程序?qū)?shù)據(jù)進(jìn)行進(jìn)一步處理。以上是本發(fā)明的較佳實(shí)施例,凡依本發(fā)明技術(shù)方案所作的改變,所產(chǎn)生的功能作用未超出本發(fā)明技術(shù)方案的范圍時(shí),均屬于本發(fā)明的保護(hù)范圍。權(quán)利要求1.一種面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法,其特征在于包括以下步驟步驟1:動(dòng)態(tài)分析受監(jiān)控程序的內(nèi)存使用行為,對(duì)內(nèi)存對(duì)象進(jìn)行分組,形成多個(gè)內(nèi)存對(duì)象組,并對(duì)各內(nèi)存對(duì)象組相關(guān)信息進(jìn)行維護(hù)和更新;所述內(nèi)存對(duì)象是指經(jīng)系統(tǒng)調(diào)用分配的內(nèi)存塊;所述內(nèi)存對(duì)象生命期是指內(nèi)存對(duì)象從被分配到被釋放的這段時(shí)間;所述內(nèi)存對(duì)象組是內(nèi)存對(duì)象的集合,每個(gè)內(nèi)存對(duì)象都采用一個(gè)元組(size,callChain)來表示,size表示內(nèi)存對(duì)象的大小,callChain表示在分配內(nèi)存對(duì)象時(shí)的棧調(diào)用(call_stack);步驟2:基于觀測(cè)到的行為特征檢測(cè)潛在的內(nèi)存泄漏;步驟3:依據(jù)相關(guān)規(guī)則進(jìn)行內(nèi)存泄漏判定。2.根據(jù)權(quán)利要求1所述的面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法,其特征在于動(dòng)態(tài)分析受監(jiān)控程序的內(nèi)存使用行為,對(duì)各內(nèi)存對(duì)象組相關(guān)信息進(jìn)行維護(hù)和更新的方法為步驟1.1:對(duì)于每一個(gè)內(nèi)存對(duì)象組,對(duì)其內(nèi)存分配與釋放的行為實(shí)施收集,記錄相關(guān)信息,包括生命期信息、內(nèi)存使用信息;所述生命期信息包括內(nèi)存對(duì)象組的最大生命期maxLifeTime、最大生命期的穩(wěn)定時(shí)間stableTime,即maxLifeTime持續(xù)為一個(gè)值的持續(xù)時(shí)間,所有的時(shí)間都以CPU時(shí)間來度量;所述內(nèi)存使用信息包括內(nèi)存對(duì)象組內(nèi)的活內(nèi)存對(duì)象信息、最后分配時(shí)間、內(nèi)存對(duì)象組占用的總內(nèi)存空間大?。徊襟E1.2:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一個(gè)活內(nèi)存對(duì)象,記錄其內(nèi)存分配時(shí)間,同一個(gè)內(nèi)存對(duì)象組內(nèi)所有活內(nèi)存對(duì)象都以雙向鏈表的形式表示,以便快速查找;步驟1.3:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一次內(nèi)存分配,即一個(gè)新的活內(nèi)存對(duì)象添加到所述雙向鏈表后,對(duì)內(nèi)存對(duì)象組的關(guān)聯(lián)信息進(jìn)行更新,包括活內(nèi)存對(duì)象信息、最后分配時(shí)間、內(nèi)存對(duì)象組占用的總內(nèi)存空間大??;步驟1.4:對(duì)于內(nèi)存對(duì)象組內(nèi)的每一次內(nèi)存釋放,也對(duì)內(nèi)存對(duì)象組的關(guān)聯(lián)信息進(jìn)行相應(yīng)的更新,包括活內(nèi)存對(duì)象信息、內(nèi)存對(duì)象組占用的總空間大小,同時(shí)通過計(jì)算被釋放內(nèi)存的分配時(shí)間與當(dāng)前時(shí)間的差值,求得被釋放內(nèi)存的生命期IifeTime;步驟1.5:如果被釋放內(nèi)存的IifeTime少于所在內(nèi)存對(duì)象組的maxLifeTime,則所述內(nèi)存對(duì)象組的maxLifeTime不作改變,且stableTime隨著CPU處理時(shí)間而增加,否則,對(duì)maxLifeTime進(jìn)行更新,且將stableTime重置為O。3.根據(jù)權(quán)利要求2所述的面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法,其特征在于檢測(cè)潛在的內(nèi)存泄漏的方法為定義在程序所有可能的執(zhí)行路徑上都不會(huì)釋放的內(nèi)存對(duì)象為總是泄漏內(nèi)存對(duì)象ALeak;定義在程序有些執(zhí)行路徑上會(huì)釋放分配,但在程序其他路徑上不會(huì)釋放分配的內(nèi)存對(duì)象為有時(shí)泄漏內(nèi)存對(duì)象SLeak;根據(jù)步驟I對(duì)內(nèi)存對(duì)象的分組,針對(duì)ALeak、SLeak兩種不同的泄漏類型,分別采用如下的方法進(jìn)行檢測(cè)檢測(cè)ALeak包括以下步驟步驟2.1:檢測(cè)每一個(gè)內(nèi)存對(duì)象組中活內(nèi)存對(duì)象的數(shù)量是否超過了預(yù)設(shè)的閾值,是則轉(zhuǎn)至步驟2.2,進(jìn)一步檢查該內(nèi)存對(duì)象組使用的內(nèi)存是否連續(xù)增長,否則轉(zhuǎn)至步驟2.3;步驟2.2:如果該內(nèi)存對(duì)象組的最后分配時(shí)間離當(dāng)前時(shí)間較近,內(nèi)存使用仍在增長,則該內(nèi)存對(duì)象組是泄漏嫌疑對(duì)象;如果最后分配時(shí)間離當(dāng)前時(shí)間較遠(yuǎn),即在一段較長時(shí)間內(nèi)都沒有內(nèi)存使用增長,則不會(huì)發(fā)生內(nèi)存泄漏;步驟2.3:如果沒有超過,則可斷定是在初始時(shí)程序分配了較多內(nèi)存對(duì)象,在整個(gè)執(zhí)行過程中這些對(duì)象都在使用,不屬于內(nèi)存泄漏;檢測(cè)SLeak的方法為檢測(cè)每一個(gè)內(nèi)存對(duì)象組中活內(nèi)存對(duì)象的生命期lifeTime,如果所述活內(nèi)存對(duì)象的活動(dòng)時(shí)間超過所在內(nèi)存對(duì)象組的maxLifeTime的兩倍,且最大生命期maxLifeTime的穩(wěn)定時(shí)間stableTime比預(yù)設(shè)閥值還長,且所述活內(nèi)存對(duì)象在maxLifeTime內(nèi)動(dòng)態(tài)內(nèi)存部分不釋放,但持續(xù)申請(qǐng),導(dǎo)致所占用的內(nèi)存越來越多,且所述活內(nèi)存對(duì)象在maxLifeTime內(nèi)已釋放,但多次重復(fù)釋放,導(dǎo)致不可預(yù)計(jì)的行為發(fā)生,則所述內(nèi)存對(duì)象組是泄漏嫌疑對(duì)象。4.根據(jù)權(quán)利要求3所述的面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法,其特征在于判定內(nèi)存泄漏的方法為步驟3.1:對(duì)于在檢測(cè)過程中已標(biāo)記為泄漏嫌疑對(duì)象的內(nèi)存對(duì)象,在預(yù)定的時(shí)間閾值內(nèi),如果所述內(nèi)存對(duì)象被再次訪問,則所述內(nèi)存對(duì)象為可能泄漏內(nèi)存對(duì)象PLeak,否則所述內(nèi)存對(duì)象確定為泄漏對(duì)象;步驟3.2:如果內(nèi)存對(duì)象為PLeak,則重置這個(gè)內(nèi)存對(duì)象的分配時(shí)間為當(dāng)前時(shí)間;如果這個(gè)內(nèi)存對(duì)象重新變?yōu)樾孤┫右蓪?duì)象,則確認(rèn)該內(nèi)存對(duì)象為泄漏對(duì)象。5.一種面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法的實(shí)現(xiàn)系統(tǒng),其特征在于包括Xen內(nèi)部緩沖區(qū)維護(hù)模塊、控制模塊、攔截模塊和監(jiān)視模塊。6.根據(jù)權(quán)利要求5所述的面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)系統(tǒng),其特征在于所述Xen內(nèi)部緩沖區(qū)維護(hù)模塊定義了若干個(gè)有關(guān)的超級(jí)調(diào)用來輔助完成對(duì)內(nèi)存相關(guān)操作的捕捉,并獲到相關(guān)數(shù)據(jù),用于泄漏對(duì)象分組和判定。7.根據(jù)權(quán)利要求5所述的面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)系統(tǒng),其特征在于所述控制模塊用以控制被測(cè)進(jìn)程,使被測(cè)進(jìn)程主動(dòng)加載攔截模塊,并向攔截模塊發(fā)送指令,使攔截模塊能對(duì)被測(cè)進(jìn)程進(jìn)行修改,攔截被測(cè)進(jìn)程內(nèi)存的申請(qǐng)和釋放操作。8.根據(jù)權(quán)利要求5所述的面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)系統(tǒng),其特征在于所述攔截模塊對(duì)被測(cè)進(jìn)程內(nèi)存的申請(qǐng)和釋放操作進(jìn)行攔截,并通過超級(jí)調(diào)用將攔截到的數(shù)據(jù)傳送到Xen內(nèi)部緩沖區(qū)維護(hù)模塊,等待進(jìn)一步處理。9.根據(jù)權(quán)利要求5所述的面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)系統(tǒng),其特征在于所述監(jiān)視模塊與攔截模塊協(xié)同作用,攔截模塊負(fù)責(zé)攔截內(nèi)存操作行為,監(jiān)視模塊對(duì)攔截到的行為進(jìn)行處理,包括分組確認(rèn)泄漏對(duì)象和可視化處理。全文摘要本發(fā)明涉及一種面向Xen虛擬化環(huán)境的運(yùn)行時(shí)內(nèi)存泄漏檢測(cè)方法及系統(tǒng),通過對(duì)Xen虛擬機(jī)內(nèi)存管理技術(shù)的分析,給出了Xen虛擬化計(jì)算環(huán)境下內(nèi)存泄漏的運(yùn)行時(shí)檢測(cè)方法,該方法的主要步驟為(1)動(dòng)態(tài)分析受監(jiān)控程序的內(nèi)存使用行為,對(duì)內(nèi)存對(duì)象進(jìn)行分組,并對(duì)各內(nèi)存對(duì)象組相關(guān)信息進(jìn)行維護(hù)和更新;(2)基于觀測(cè)到的行為特征檢測(cè)潛在的內(nèi)存泄漏;(3)依據(jù)相關(guān)規(guī)則進(jìn)行內(nèi)存泄漏判定。與現(xiàn)有技術(shù)相比,本發(fā)明能跨操作系統(tǒng)平臺(tái)、跨語言開發(fā)環(huán)境對(duì)運(yùn)行時(shí)內(nèi)存泄漏檢測(cè),適用范圍廣,具有較好的性能,能提升軟件開發(fā)行業(yè)特別是內(nèi)存受限的軟件產(chǎn)品質(zhì)量與開發(fā)效率,縮短軟件開發(fā)的工期,直接節(jié)約了開發(fā)成本,能帶來良好的經(jīng)濟(jì)效益和社會(huì)效益。文檔編號(hào)G06F11/36GK103064784SQ20121049948公開日2013年4月24日申請(qǐng)日期2012年11月29日優(yōu)先權(quán)日2012年11月29日發(fā)明者肖如良,姜軍,胡耀,李鵬澎,倪友聰,杜欣申請(qǐng)人:福建師范大學(xué)