利用虛擬化平臺(tái)進(jìn)行內(nèi)存泄露探測(cè)_第1頁(yè)
利用虛擬化平臺(tái)進(jìn)行內(nèi)存泄露探測(cè)_第2頁(yè)
利用虛擬化平臺(tái)進(jìn)行內(nèi)存泄露探測(cè)_第3頁(yè)
利用虛擬化平臺(tái)進(jìn)行內(nèi)存泄露探測(cè)_第4頁(yè)
利用虛擬化平臺(tái)進(jìn)行內(nèi)存泄露探測(cè)_第5頁(yè)
已閱讀5頁(yè),還剩26頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

利用虛擬化平臺(tái)進(jìn)行內(nèi)存泄露探測(cè)摘要:本文利用虛擬機(jī)管理器,透明地記錄應(yīng)用程序?qū)Y源的申請(qǐng)、釋放以及使用情況,提供了探測(cè)內(nèi)存泄露的輔助信息。此機(jī)制首先不需要修改或重新編譯源程序;其次,帶來(lái)的性能損失很小。兩者結(jié)合可以構(gòu)建在線內(nèi)存泄露探測(cè)和匯報(bào)機(jī)制。不僅如此,基于虛擬環(huán)境的內(nèi)存泄露探測(cè)還具備通用性,且不需要特殊的硬件支持。所有這些特性,是已有的解決方案所不能兼有的。實(shí)驗(yàn)結(jié)果表明:基于虛擬機(jī)環(huán)境的內(nèi)存泄露探測(cè)機(jī)制具有實(shí)用性,性能損失也被控制在10%以內(nèi),能夠運(yùn)用在實(shí)際的生產(chǎn)環(huán)境中。關(guān)鍵詞:內(nèi)存泄露探測(cè);虛擬機(jī);虛擬化平臺(tái);虛擬機(jī)管理器

1、介紹 內(nèi)存泄露是指被申請(qǐng)的內(nèi)存資源在程序運(yùn)行的某一時(shí)刻后再也不被使用和釋放。如果被泄露的是虛擬內(nèi)存,則此程序本身能夠使用的虛擬內(nèi)存空間因此變少;如果被泄露的是物理內(nèi)存,則整個(gè)系統(tǒng)減少了能夠使用的物理地址。內(nèi)存泄露會(huì)使應(yīng)用程序申請(qǐng)動(dòng)態(tài)內(nèi)存失敗,導(dǎo)致服務(wù)中止;嚴(yán)重時(shí)會(huì)導(dǎo)致整個(gè)系統(tǒng)因資源耗竭而崩潰。對(duì)于運(yùn)行時(shí)間很短的程序,內(nèi)存泄露一般不是問(wèn)題;但是對(duì)于長(zhǎng)期運(yùn)行的程序,例如運(yùn)行在服務(wù)器上的服務(wù)和操作系統(tǒng)本身,內(nèi)存泄露會(huì)帶來(lái)嚴(yán)重的后果,可能會(huì)導(dǎo)致系統(tǒng)服務(wù)中止。一直以來(lái),內(nèi)存泄露都是造成計(jì)算機(jī)安全事故的主要原因之一。 一些編程語(yǔ)言,如Java,通過(guò)垃圾回收等的方式,自身提供了內(nèi)存回收的機(jī)制。這種機(jī)制不但不能保證消除內(nèi)存泄露,而且還會(huì)帶來(lái)性能的損失。而另外執(zhí)行效率很高的一些編程語(yǔ)言,如C和C++,則將內(nèi)存分配和釋放的操作完全交付給程序員;在邏輯非常龐大的程序中,內(nèi)存泄露很難避免。因?yàn)閮?nèi)存泄露探測(cè)的重要性,先前已經(jīng)有很多這方面的工作。這些工作基本分為兩類:第一類是靜態(tài)檢查程序語(yǔ)義。這類方法認(rèn)為,正確的程序代碼,應(yīng)該符合預(yù)定的規(guī)則,例如,通過(guò)malloc函數(shù)申請(qǐng)的內(nèi)存,在接下來(lái)運(yùn)行的所有代碼分支都應(yīng)該有一個(gè)free函數(shù)。例如將代碼的路徑抽象為布爾限制路徑,對(duì)動(dòng)態(tài)內(nèi)存的指針加以跟蹤。對(duì)于大型的工程,這個(gè)方法比較耗時(shí),例如分析GNU/Linux的內(nèi)核代碼需要一個(gè)處理器一整天的時(shí)間[1]。也有將代碼抽象為一個(gè)變量流通圖的,圖的邊表示代碼分支[2]。這類方法直接對(duì)代碼進(jìn)行分析,實(shí)現(xiàn)復(fù)雜,目前還有一些難點(diǎn)尚未解決,例如循環(huán)的處理[1]。另一類是運(yùn)行時(shí)動(dòng)態(tài)檢測(cè)法。即在程序運(yùn)行時(shí)記錄程序動(dòng)態(tài)分配的內(nèi)存資源和釋放信息,然后分析是否存在內(nèi)存泄露。例如Purify[3]和SafeMem[4],都屬于這一類。動(dòng)態(tài)檢測(cè)法受限于測(cè)試程序,因?yàn)闇y(cè)試程序所覆蓋的代碼非常有限,無(wú)法激發(fā)出所有潛在的問(wèn)題。 本文通過(guò)虛擬機(jī)管理器(VirtualMachineMonitor,VMM)平臺(tái),在其上虛擬機(jī)(VirtualMachine,GuestOS,VM)運(yùn)行時(shí),動(dòng)態(tài)截獲虛擬機(jī)中申請(qǐng)和釋放內(nèi)存的函數(shù),并記錄下來(lái),用于輔助甄別內(nèi)存泄露,是基于第二類方法的。通過(guò)內(nèi)存虛擬化技術(shù)的協(xié)助,我們可以監(jiān)控應(yīng)用程序?qū)@些內(nèi)存資源的應(yīng)用情況。然后,應(yīng)用一些規(guī)則,找出內(nèi)存泄露的嫌疑。例如長(zhǎng)時(shí)間未被釋放、且沒(méi)有被訪問(wèn)的內(nèi)存可能是內(nèi)存泄露。這種方法相對(duì)現(xiàn)有的方法有以下優(yōu)點(diǎn): 首先,既不需要修改被探測(cè)程序的源代碼,也不需要重新編譯,為被測(cè)試代碼提供了透明性。Purify和SafeMem,前者通過(guò)編譯插入指令以獲取應(yīng)用程序訪問(wèn)內(nèi)存的所有行為,然后這些行為被用于判斷內(nèi)存泄露和內(nèi)存訪問(wèn)地址越界等問(wèn)題。SafeMem則需要重新封裝資源申請(qǐng)和釋放函數(shù),甚至需要給操作系統(tǒng)添加新的系統(tǒng)調(diào)用,這些需求一定程度上不利于它們的應(yīng)用。其次,如果探測(cè)內(nèi)存泄露方法給應(yīng)用程序帶來(lái)很多性能損失或者占用很大額外資源的話,其應(yīng)用只能僅限于程序調(diào)試階段,其可發(fā)現(xiàn)的內(nèi)存泄露受限于測(cè)試用例。Purify雖然能夠捕捉到程序中大量的內(nèi)存訪問(wèn)問(wèn)題,但是,因?yàn)樾枰孬@應(yīng)用程序所有的內(nèi)存操作,Purify導(dǎo)致應(yīng)用程序的性能損失很大,通常應(yīng)用程序的性能降低達(dá)到2到3倍,或者更多[3]。性能的降低限制了其使用范圍,而且加重了其對(duì)測(cè)試程序的依賴。本文中的內(nèi)存泄露探測(cè)機(jī)制基于虛擬機(jī)的實(shí)現(xiàn),性能損失經(jīng)過(guò)測(cè)試,少于10%,能夠在真實(shí)服務(wù)中使用。這同時(shí)帶來(lái)的另外一個(gè)優(yōu)點(diǎn)在于,在真實(shí)使用中,代碼的執(zhí)行覆蓋范圍更廣,能夠發(fā)現(xiàn)潛在的內(nèi)存泄露。 另外,本論文不但適用于用戶態(tài)的應(yīng)用程序,而且還適用于操作系統(tǒng)內(nèi)核。存在于內(nèi)核中的內(nèi)存泄露,比應(yīng)用程序中的內(nèi)存泄露帶來(lái)的危害更大,而且調(diào)試更困難。盡管有很多工具用于測(cè)試用戶態(tài)程序的內(nèi)存泄露,但是調(diào)試內(nèi)核代碼的工具仍舊比較缺乏。PinOS[5]在虛擬機(jī)管理器之上,通過(guò)軟件動(dòng)態(tài)翻譯的方法,提供了調(diào)試操作系統(tǒng)內(nèi)核代碼的機(jī)制。然而,軟件動(dòng)態(tài)翻譯使得其性能下降很大,大多數(shù)情況下降低到50到60倍,這限制了其使用環(huán)境,難以在真實(shí)環(huán)境中使用。而且,其運(yùn)行時(shí)需要插入部分代碼到虛擬機(jī)的內(nèi)核地址空間,因此占用操作系統(tǒng)的一部分地址空間,這破壞了透明性。本文基于虛擬機(jī)管理器的實(shí)現(xiàn)也提供了平臺(tái)通用性,其既適用于GNU/Linux操作系統(tǒng),也適用于Windows操作系統(tǒng)。對(duì)操作系統(tǒng)的版本也不做要求,只要其代碼體系符合IntelX86的指令規(guī)范。而SafeMem雖然性能降低很小,但是需要給操作系統(tǒng)添加新的系統(tǒng)調(diào)用接口和系統(tǒng)調(diào)用處理函數(shù),因此欠缺了平臺(tái)的通用性。最后,本論文的機(jī)制不需要特殊硬件的支持,而SafeMem是基于ECC控制器實(shí)現(xiàn)的。 在接下來(lái)的章節(jié)中,首先總體介紹利用虛擬化平臺(tái)進(jìn)行內(nèi)存探測(cè)的機(jī)制;其次詳細(xì)介紹對(duì)運(yùn)行在虛擬機(jī)中的應(yīng)用程序申請(qǐng)和釋放內(nèi)存資源的捕獲和記錄,然后分析應(yīng)用程序所申請(qǐng)的內(nèi)存資源,推選出存在內(nèi)存泄露的嫌疑進(jìn)行監(jiān)控。在實(shí)驗(yàn)章節(jié)中,本文描述了基于虛擬平臺(tái)進(jìn)行內(nèi)存泄露探測(cè)的有效性和性能代價(jià)。最后是結(jié)論和下一步工作。2、實(shí)現(xiàn)原理 內(nèi)存泄露是指已經(jīng)被申請(qǐng)的內(nèi)存資源沒(méi)有被合理地釋放,而導(dǎo)致這部分資源不能被系統(tǒng)重新利用的一種現(xiàn)象。內(nèi)存泄露廣泛存在或者隱藏于程序之中,被泄漏的內(nèi)存資源不能被重新利用且不再被訪問(wèn)。對(duì)于應(yīng)用程序,內(nèi)存泄露會(huì)使得應(yīng)用程序的虛擬內(nèi)存空間耗竭,導(dǎo)致任務(wù)的中斷和失敗。對(duì)于操作系統(tǒng),內(nèi)存泄露不僅會(huì)減少可用的內(nèi)核虛擬空間,而且還會(huì)不斷蠶食整個(gè)系統(tǒng)可用的物理內(nèi)存頁(yè)面,導(dǎo)致整機(jī)不得不重起。 內(nèi)存申請(qǐng)和釋放的接口具有統(tǒng)一、簡(jiǎn)單的特色,例如Windows提供的動(dòng)態(tài)內(nèi)存管理接口GlobalAlloc和GlobalFree、Posix規(guī)定的malloc和free接口、Linux內(nèi)核的vmalloc和vfree以及get_page和put_page等接口。某些應(yīng)用程序?qū)崿F(xiàn)了自身的內(nèi)存管理,但是其接口也是比較統(tǒng)一的。這些接口不但統(tǒng)一簡(jiǎn)單,其數(shù)量也非常有限。正常情況下,通過(guò)某個(gè)申請(qǐng)函數(shù)獲得資源需要通過(guò)對(duì)應(yīng)的釋放函數(shù)來(lái)釋放。本文利用這一點(diǎn),在虛擬化平臺(tái)中透明地截取了資源申請(qǐng)和釋放的接口,維護(hù)一個(gè)動(dòng)態(tài)資源使用列表,詳盡和全面地掌握被監(jiān)控對(duì)象使用內(nèi)存資源的情況。 如果有內(nèi)存泄露存在的話,這個(gè)列表理論上包含了所有被泄漏的內(nèi)存,但又不僅限于被泄漏的內(nèi)存,因?yàn)楸惶摂M機(jī)正確使用的動(dòng)態(tài)內(nèi)存資源也包含在這個(gè)列表中。接下來(lái)的工作是從這個(gè)列表中選擇出最有可能是內(nèi)存泄露的項(xiàng)。選擇的主導(dǎo)思想一是某個(gè)地址持續(xù)地分配長(zhǎng)時(shí)間不被釋放的內(nèi)存;二是被占用但長(zhǎng)時(shí)間未被訪問(wèn)的內(nèi)存。前者可以從記錄獲取,實(shí)現(xiàn)后者需要分兩步:首先確定被監(jiān)控的對(duì)象,然后通過(guò)內(nèi)存虛擬化技術(shù)進(jìn)行監(jiān)控。 在接下來(lái)的幾個(gè)小節(jié)中,詳細(xì)介紹每個(gè)步驟的設(shè)計(jì)原理和方案。2.1截獲資源申請(qǐng)和釋放 Purify和SafeMem等實(shí)現(xiàn)方案通過(guò)修改源代碼或者修改編譯器的方式,來(lái)截取資源申請(qǐng)和釋放;而通過(guò)虛擬化平臺(tái)可以更簡(jiǎn)單更透明地實(shí)現(xiàn)這個(gè)功能。我們以malloc和free為例來(lái)說(shuō)明,下面列出了一小段常見(jiàn)的代碼。 void*PTR=malloc(LEN); if(PTR==NULL)err(“Outofmemory.”); /*utilizingthememorystartingatPTRofsizeLEN*/ if(PTR)free(PTR); 這段C語(yǔ)言代碼首先通過(guò)malloc函數(shù)申請(qǐng)長(zhǎng)度為L(zhǎng)EN個(gè)字節(jié)的動(dòng)態(tài)內(nèi)存,然后判斷是否申請(qǐng)成功。如果成功,則使用這些內(nèi)存資源進(jìn)行計(jì)算。最后,當(dāng)不再需要PTR所指的資源時(shí),通過(guò)free函數(shù)釋放這些內(nèi)存。在這個(gè)場(chǎng)景中,我們不僅需要截獲malloc函數(shù)的調(diào)用,獲取其參數(shù)和返回結(jié)果,而且也需要截獲free函數(shù)的調(diào)用,獲取其參數(shù),也即被釋放的動(dòng)態(tài)資源。換句話說(shuō),應(yīng)用程序當(dāng)前正在使用的動(dòng)態(tài)內(nèi)存信息,包括其起始地址、長(zhǎng)度、時(shí)間和調(diào)用IP地址都需要在虛擬機(jī)管理器中維護(hù)。 在虛擬化平臺(tái)中,可以通過(guò)替換指令的方式,透明地截獲申請(qǐng)函數(shù)和釋放函數(shù)。為了實(shí)現(xiàn)透明的結(jié)果,首先分析一下上面C語(yǔ)言程序在Linux操作系統(tǒng)之上對(duì)應(yīng)的匯編代碼:8048426:890424 mov%eax,(%esp)8048429:e8defeffff call804830c<malloc@plt>804842e:8945fc mov%eax,0xfffffffc(%ebp)8048431:837dfc00 cmpl$0x0,0xfffffffc(%ebp)8048435:7518 jne804844f<main+0x4f>8048437:c7042454850408 movl$0x8048554,(%esp)804843e:e8e9feffff call804832c<printf@plt>8048443:c7042401000000 movl$0x1,(%esp)804844a:e8edfeffff call804833c<exit@plt>804844f:837dfc00 cmpl$0x0,0xfffffffc(%ebp)8048453:740b je8048460<main+0x60>8048455:8b45fc mov0xfffffffc(%ebp),%eax8048458:890424 mov%eax,(%esp)804845b:e8ecfeffff call804834c<free@plt> 可以看到,在地址為0x8048426的地方,變量LEN中保存的數(shù)值被壓到棧上,接下來(lái)的一條指令調(diào)用了malloc函數(shù),程序的運(yùn)行跳轉(zhuǎn)到malloc函數(shù)所在的地址0x804830c。在malloc函數(shù)返回后,程序在地址0x804842e處繼續(xù)執(zhí)行。如果malloc函數(shù)申請(qǐng)資源成功,程序最終會(huì)在地址0x804845b處調(diào)用free函數(shù),釋放這段內(nèi)存空間。 內(nèi)存資源申請(qǐng)函數(shù)和釋放函數(shù),例如malloc和free,作為系統(tǒng)的調(diào)用接口,其在內(nèi)存中的地址很容易捕獲得到,在上面的示例程序中,malloc和free的地址分別為0x804830c和0x804834c。獲得內(nèi)存申請(qǐng)函數(shù)和釋放函數(shù)的地址之后,截獲其執(zhí)行需要如下幾個(gè)步驟:(1)在函數(shù)地址處(例如0x804830c處)插入能夠使得虛擬機(jī)無(wú)條件陷入到虛擬機(jī)管理器的指令。例如非法指令,在Intel的VT平臺(tái)中可以插入VMCALL指令。我們把這種指令稱為陷入指令,原位置被替換的指令稱為被替換指令,把被植入陷入指令的函數(shù)稱為受監(jiān)控函數(shù)。(2)運(yùn)行在虛擬機(jī)中的應(yīng)用程序調(diào)用受監(jiān)控函數(shù)(例如malloc)之后,虛擬機(jī)馬上陷入虛擬機(jī)管理器。(3)在虛擬機(jī)管理器中,分析受監(jiān)控函數(shù)的類別,分析其參數(shù),獲取函數(shù)調(diào)用棧,更新應(yīng)用程序占用內(nèi)存資源的信息。如果是資源申請(qǐng)函數(shù)則增加內(nèi)存占用信息,而資源釋放函數(shù)則需要?jiǎng)h除相應(yīng)的內(nèi)存信息。例如,如果陷入的函數(shù)是malloc,其只有一個(gè)參數(shù)表明申請(qǐng)內(nèi)存的長(zhǎng)度,我們可以在當(dāng)前應(yīng)用程序的堆棧上獲得。如果陷入的是free函數(shù),其參數(shù)表明需要釋放的內(nèi)存。這里獲取函數(shù)調(diào)用棧的目的是為了程序員調(diào)試的方便。(4)在虛擬機(jī)管理器中模擬執(zhí)行被替換指令。之所以不恢復(fù)被替換指令的原因是,為了保證能監(jiān)控到應(yīng)用程序并發(fā)調(diào)用該受監(jiān)控函數(shù),例如多線程程序中多個(gè)線程有可能同時(shí)通過(guò)調(diào)用malloc函數(shù)申請(qǐng)內(nèi)存資源。(5)如果該受監(jiān)控函數(shù)在申請(qǐng)資源,在陷入指令的下一條指令處(在上述例子中,地址0x804842e處),需要插入陷入指令,以便讓我們獲悉函數(shù)調(diào)用結(jié)束,分析申請(qǐng)結(jié)果。(6)虛擬機(jī)管理器命令虛擬機(jī)繼續(xù)執(zhí)行,虛擬機(jī)會(huì)執(zhí)行受監(jiān)控函數(shù)的其它代碼,執(zhí)行結(jié)束后,返回到調(diào)用處,上例中監(jiān)控malloc的第一次調(diào)用,則是地址0x804842e處。(7)返回處陷入,因?yàn)椴襟E5已經(jīng)將一個(gè)陷入指令插入到返回處;在虛擬機(jī)管理器中,分析受監(jiān)控函數(shù)返回的結(jié)果。對(duì)于malloc函數(shù),其返回結(jié)果是所申請(qǐng)到內(nèi)存資源的地址,如果申請(qǐng)失敗,則返回值是NULL。 通過(guò)以上方法獲取應(yīng)用程序的動(dòng)態(tài)內(nèi)存資源使用情況之后,我們即時(shí)地維護(hù)應(yīng)用程序申請(qǐng)動(dòng)態(tài)內(nèi)存的列表。如果應(yīng)用程序中存在內(nèi)存泄露的話,被泄露的內(nèi)存必然在我們所維護(hù)的表中。從動(dòng)態(tài)內(nèi)存列表中精確找出被泄露的內(nèi)存項(xiàng)是一個(gè)難點(diǎn);然而,我們可以先找到疑似泄露的動(dòng)態(tài)內(nèi)存項(xiàng),然后將信息(函數(shù)調(diào)用棧,調(diào)用地址和申請(qǐng)資源大小等)交由程序員處理。本論文的目標(biāo)是,找到內(nèi)存泄露的嫌疑項(xiàng),并提高準(zhǔn)確率。除此之外,通過(guò)本文的方法,還可捕捉到程序中多次釋放資源的錯(cuò)誤操作,例如將一段動(dòng)態(tài)內(nèi)存調(diào)用free釋放后,又再次調(diào)用free釋放,根據(jù)free接口的規(guī)范,其結(jié)果是不可預(yù)料的,也會(huì)對(duì)程序的正常運(yùn)行帶來(lái)隱患。 本小節(jié)闡述了截獲內(nèi)存申請(qǐng)和釋放的機(jī)制,接下來(lái)的兩個(gè)小節(jié)中,將著重介紹推選內(nèi)存泄露嫌疑項(xiàng)的規(guī)則和步驟,以及提高推選準(zhǔn)確率的一些策略和方法。2.2判斷內(nèi)存泄露的規(guī)則 2.1節(jié)中介紹了截獲應(yīng)用程序申請(qǐng)和釋放動(dòng)態(tài)內(nèi)存的機(jī)制。這個(gè)機(jī)制能夠使得虛擬機(jī)管理器維護(hù)應(yīng)用程序當(dāng)前使用的全部動(dòng)態(tài)內(nèi)存信息,這些信息包括受監(jiān)控函數(shù)的調(diào)用IP地址、動(dòng)態(tài)內(nèi)存申請(qǐng)函數(shù)的種類、所申請(qǐng)動(dòng)態(tài)內(nèi)存的地址和大小以及申請(qǐng)時(shí)間等。如果應(yīng)用程序存在內(nèi)存泄露的話,那么被泄露的內(nèi)存就隱藏在我們維護(hù)的列表中。我們判斷是否是內(nèi)存泄露的嫌疑基于如下幾條規(guī)則:(1)在應(yīng)用程序運(yùn)行的過(guò)程中,長(zhǎng)時(shí)間未被應(yīng)用程序訪問(wèn)的動(dòng)態(tài)內(nèi)存;這里的運(yùn)行是指應(yīng)用程序?qū)嶋H占用處理器的狀態(tài),不包括程序阻塞等待的狀態(tài)。(2)在應(yīng)用程序的某一地址持續(xù)申請(qǐng)動(dòng)態(tài)內(nèi)存且部分不釋放,導(dǎo)致應(yīng)用程序占用的動(dòng)態(tài)內(nèi)存隨著運(yùn)行時(shí)間的延續(xù)越來(lái)越多;(3)在應(yīng)用程序退出時(shí),未被釋放的內(nèi)存段。規(guī)則1基于被泄漏內(nèi)存的最基本的特征:應(yīng)用程序在語(yǔ)義層面上,丟棄了內(nèi)存段并不再訪問(wèn)該內(nèi)存段。規(guī)則1需要虛擬機(jī)管理器對(duì)應(yīng)用程序的內(nèi)存的訪問(wèn)情況進(jìn)行監(jiān)控。這種監(jiān)控行為是需要虛擬機(jī)管理器付出性能代價(jià)的,因?yàn)樵诒O(jiān)控中,會(huì)導(dǎo)致虛擬機(jī)管理器對(duì)虛擬機(jī)正常運(yùn)行添加額外的干預(yù)和陷入,我們?cè)谙乱恍」?jié)中會(huì)詳細(xì)描述監(jiān)控的步驟。監(jiān)控應(yīng)用程序所申請(qǐng)的所有內(nèi)存資源的訪問(wèn)是不太實(shí)際的,因?yàn)檫@有可能引起大量的虛擬機(jī)陷入,嚴(yán)重影響虛擬機(jī)管理器的整體性能。為了克服這一點(diǎn),從而減少虛擬機(jī)管理器性能的損失,應(yīng)當(dāng)降低被監(jiān)控內(nèi)存片斷的數(shù)目。在本文的設(shè)計(jì)中,監(jiān)控機(jī)制和監(jiān)控策略是分開(kāi)的。我們?cè)谔摂M機(jī)管理器中添加了監(jiān)控機(jī)制,而決定誰(shuí)被監(jiān)控、誰(shuí)不被監(jiān)控、被監(jiān)控內(nèi)存片斷的數(shù)目等策略性決定則在高層動(dòng)態(tài)設(shè)定。監(jiān)控策略會(huì)根據(jù)動(dòng)態(tài)內(nèi)存的監(jiān)控歷史、分配時(shí)間和虛擬機(jī)的性能反饋等因素進(jìn)行判斷。規(guī)則2是基于統(tǒng)計(jì)的,不需要監(jiān)控動(dòng)態(tài)內(nèi)存的被訪問(wèn)情況,因此開(kāi)銷比規(guī)則1少,但是準(zhǔn)確性比規(guī)則1差。此規(guī)則基于這樣的觀察,內(nèi)存泄露的點(diǎn)具有重復(fù)性,在某一IP點(diǎn)上如果發(fā)生過(guò)內(nèi)存泄露,那么在此點(diǎn)上還會(huì)發(fā)生內(nèi)存泄露。規(guī)則3基于對(duì)良好編程原則的考慮:程序應(yīng)該在退出時(shí),已經(jīng)優(yōu)雅地釋放掉所有申請(qǐng)的資源,而不是將這些清理工作托付給操作系統(tǒng)??傊?,我們根據(jù)應(yīng)用程序?qū)ζ渌暾?qǐng)的資源使用情況的統(tǒng)計(jì),來(lái)推測(cè)是否有內(nèi)存泄露發(fā)生。規(guī)則1基于如下考慮:因?yàn)楸恍孤兜膬?nèi)存的特征之一是不再被應(yīng)用程序訪問(wèn),所以最好的嫌疑者是那些在應(yīng)用程序的運(yùn)行中,長(zhǎng)時(shí)間沒(méi)有被訪問(wèn)的動(dòng)態(tài)內(nèi)存。規(guī)則2基于如下考慮:程序的執(zhí)行線隨著上下文的不同而不同,在某個(gè)執(zhí)行線上程序員可能會(huì)忘記釋放資源。如果程序不斷經(jīng)過(guò)這個(gè)忘記釋放資源的執(zhí)行線,則會(huì)不斷產(chǎn)生內(nèi)存泄露。規(guī)則3基于編程習(xí)慣。2.3監(jiān)控內(nèi)存 本小節(jié)主要描述在虛擬機(jī)管理器中,實(shí)現(xiàn)對(duì)應(yīng)用程序所申請(qǐng)動(dòng)態(tài)內(nèi)存的訪問(wèn)進(jìn)行監(jiān)控的機(jī)制。根據(jù)判斷內(nèi)存泄露的規(guī)則1,在程序運(yùn)行期間長(zhǎng)時(shí)間未被有效利用的動(dòng)態(tài)內(nèi)存資源,可能是被泄漏的內(nèi)存。為了了解動(dòng)態(tài)內(nèi)存資源被利用的情況,需要對(duì)該動(dòng)態(tài)內(nèi)存資源進(jìn)行訪問(wèn)監(jiān)控。監(jiān)控的基本思想是,在應(yīng)用程序訪問(wèn)被監(jiān)控的動(dòng)態(tài)內(nèi)存時(shí),虛擬機(jī)管理器能夠獲悉這一訪問(wèn)行為。Safemem利用了硬件ECC實(shí)現(xiàn)了監(jiān)控,而虛擬機(jī)管理器不需要額外的硬件支持,通過(guò)內(nèi)存虛擬化即可實(shí)現(xiàn)監(jiān)控。本小節(jié)內(nèi)容首先著重描述基于影子頁(yè)表的內(nèi)存虛擬化方法,其次描述在內(nèi)存虛擬化方法中實(shí)現(xiàn)內(nèi)存監(jiān)控的原理和方法,最后分析在虛擬機(jī)管理器中內(nèi)存監(jiān)控的有效性。2.3.1內(nèi)存虛擬化方法虛擬機(jī)與傳統(tǒng)計(jì)算機(jī)相比,其內(nèi)存系統(tǒng)多了一種地址,共包括以下三種地址:機(jī)器地址(HostPhysicalAddress,HPA):指真實(shí)硬件的機(jī)器地址,即地址總線上應(yīng)該出現(xiàn)的地址信號(hào);物理地址(GuestPhysicalAddress,GPA):指經(jīng)過(guò)VMM抽象的、虛擬機(jī)所看到的偽物理地址;虛擬地址(GuestVirtualAddress,GVA):指GuestOS提供給其應(yīng)用程序使用的線性地址空間。顯然,VMM的內(nèi)存模塊負(fù)責(zé)完成物理地址到機(jī)器地址的映射,我們將這個(gè)映射記為f;同時(shí),GuestOS的內(nèi)存管理模塊要完成虛擬地址到物理地址的映射,我們將這個(gè)映射記為g。于是,虛擬地址、物理地址和真實(shí)地址之間的關(guān)系如圖1所示。圖1機(jī)器地址,物理地址和虛擬地址在沒(méi)有硬件內(nèi)存虛擬化支持的情況下,KVM實(shí)現(xiàn)內(nèi)存虛擬化的方法是影子頁(yè)表技術(shù)[6][7]。影子頁(yè)表技術(shù)為GuestOS的每個(gè)頁(yè)表維護(hù)一個(gè)“影子頁(yè)表”,并將合成后的映射關(guān)系寫入到“影子”中,GuestOS的頁(yè)表內(nèi)容則保持不變。最后,VMM將影子頁(yè)表交給內(nèi)存管理模塊(MemoryManagementUnit,MMU)進(jìn)行地址轉(zhuǎn)換。試舉一例說(shuō)明:假設(shè)一個(gè)運(yùn)行在GuestOS中的進(jìn)程,當(dāng)其訪問(wèn)0x12345678這個(gè)虛擬地址時(shí),因?yàn)樵谟白禹?yè)表中尚未為其建立頁(yè)表項(xiàng),所以會(huì)產(chǎn)生缺頁(yè)異常,使得GuestOS陷入到虛擬機(jī)管理器中。虛擬機(jī)管理器首先查看GuestOS的頁(yè)表中是否存在有效的映射g。如果不存在,則將異常交付給GuestOS處理。如果存在,虛擬機(jī)管理器在影子頁(yè)表項(xiàng)中直接建立映射f?g,從虛擬地址頁(yè)0x12345000轉(zhuǎn)換為物理頁(yè)的地址。當(dāng)此影子頁(yè)表項(xiàng)被清除時(shí),虛擬機(jī)管理器再負(fù)責(zé)將影子頁(yè)表項(xiàng)中的Dirty位和Access位同步到GuestOS的頁(yè)表中去。2.3.2內(nèi)存監(jiān)控的原理和方法 內(nèi)存監(jiān)控的一個(gè)選擇是通過(guò)管理虛擬機(jī)的影子頁(yè)表實(shí)現(xiàn)。在虛擬機(jī)運(yùn)行時(shí),內(nèi)存管理模塊載入影子頁(yè)表,試圖完成從GVA到HPA的映射。如果影子頁(yè)表中已經(jīng)存在某個(gè)GVA到其HPA的映射,那么這個(gè)轉(zhuǎn)換過(guò)程會(huì)自動(dòng)完成;否則,虛擬機(jī)會(huì)陷入到虛擬機(jī)管理器中,由后者完善GVA到HPA的映射?;谟白禹?yè)表的這種特征,通過(guò)如下步驟即可完成對(duì)內(nèi)存的監(jiān)控。圖2內(nèi)存監(jiān)控原理 首先,計(jì)算出內(nèi)存片斷所跨越的所有頁(yè)面,例如在頁(yè)面大小為4K的虛擬機(jī)中,首地址為0x80a8400,長(zhǎng)度為10KB的內(nèi)存片斷,跨越了3個(gè)頁(yè)面:其中占第一個(gè)和第三個(gè)頁(yè)面的部分,完全占用第二個(gè)頁(yè)面(如圖2a所示)。接著,在影子頁(yè)表中消除對(duì)這些頁(yè)面的GVA到HPA的映射關(guān)系。因?yàn)檫@些頁(yè)面的映射關(guān)系被消除,那么只要虛擬機(jī)試圖訪問(wèn)該內(nèi)存片斷,都會(huì)導(dǎo)致虛擬機(jī)的陷入(如圖2b所示)。最后,在虛擬機(jī)陷入時(shí),分析陷入指令所訪問(wèn)的內(nèi)存地址是否屬于該內(nèi)存片斷。 通過(guò)內(nèi)存虛擬化機(jī)制實(shí)現(xiàn)的內(nèi)存監(jiān)控,是基于頁(yè)面級(jí),即所監(jiān)控的最小內(nèi)存單位是內(nèi)存頁(yè)。內(nèi)存頁(yè)通常大小是4K,也有其它大小,例如2M和4M。在進(jìn)行監(jiān)控時(shí),虛擬機(jī)對(duì)頁(yè)面范圍內(nèi)的所有內(nèi)存地址訪問(wèn)都會(huì)導(dǎo)致陷入,因此,監(jiān)控的單位大小越小越好。 基于硬件ECC的監(jiān)控是更細(xì)粒度的監(jiān)控機(jī)制,被SafeMem所采用。如果虛擬機(jī)管理器存在ECC的支持,也能夠?qū)崿F(xiàn)cacheline大小粒度的監(jiān)控,SafeMem所使用的方法同樣適用于虛擬機(jī)管理器。 這種內(nèi)存監(jiān)控的原理,也適用于其它內(nèi)存虛擬化方法,例如直接頁(yè)表訪問(wèn)。即使是硬件輔助內(nèi)存虛擬化技術(shù),例如EPT(ExtendedPageTables)[8]或者NPT(NestedPageTables)[9],在其上實(shí)現(xiàn)內(nèi)存監(jiān)控。核心思想是通用的,即從虛擬機(jī)管理器中,消除虛擬機(jī)從GVA到HPA的內(nèi)存地址映射關(guān)系。2.3.3虛擬機(jī)管理器監(jiān)控內(nèi)存的有效性分析 虛擬機(jī)管理器監(jiān)控內(nèi)存引入的性能開(kāi)銷主要源于截獲資源申請(qǐng)和釋放的函數(shù)和影子頁(yè)表導(dǎo)致的虛擬機(jī)陷入。每次陷入的開(kāi)銷公式如下:COST[陷入]=COST[VM切換到VMM]+COST[分析+模擬指令]+COST[VMM切換到VM]+COST[Cache]+COST[TLB] 虛擬機(jī)和虛擬機(jī)管理器之間的切換會(huì)引入很大的性能開(kāi)銷。首先,切換本身會(huì)耗費(fèi)很多的處理器周期,因?yàn)樵谇袚Q過(guò)程中,處理器不僅需要保存原狀態(tài),而且需要載入新?tīng)顟B(tài)。其次,這種切換還會(huì)導(dǎo)致額外的Cache失效,因?yàn)樘摂M機(jī)管理器和虛擬機(jī)共享Cache且代碼和數(shù)據(jù)并不相同。最后,TLB(TranslateLookasideBuffer)[8]被刷新的開(kāi)銷。TLB緩存著虛擬地址到物理地址的映射,避免了MMU在地址映射時(shí)對(duì)存放在內(nèi)存中的頁(yè)表的重復(fù)遍歷訪問(wèn)。因?yàn)樘摂M機(jī)管理器和虛擬機(jī)使用不同的頁(yè)表,所以每次切換都會(huì)導(dǎo)致TLB的刷新操作,這個(gè)開(kāi)銷是非常大的。然而,隨著硬件的不斷發(fā)展,新的技術(shù)例如VPID(VirtualProcessID)[8],能夠避免或減少在虛擬機(jī)管理器和虛擬機(jī)之間切換時(shí)TLB的刷新,從而降低TLB刷新的開(kāi)銷。 截獲資源申請(qǐng)和釋放的函數(shù)的開(kāi)銷和這些函數(shù)調(diào)用點(diǎn)的次數(shù)成正比。性能的主要開(kāi)銷在于對(duì)內(nèi)存使用進(jìn)行監(jiān)控。虛擬機(jī)管理器監(jiān)控動(dòng)態(tài)內(nèi)存的訪問(wèn)情況,會(huì)導(dǎo)致額外的附帶開(kāi)銷。為了監(jiān)控占用部分內(nèi)存頁(yè)面的動(dòng)態(tài)內(nèi)存,需要監(jiān)控整個(gè)頁(yè)面被訪問(wèn)情況。如果該頁(yè)面中,動(dòng)態(tài)內(nèi)存片斷之外當(dāng)前被虛擬機(jī)監(jiān)控器頻繁使用,也即非常熱的頁(yè)面,則對(duì)該頁(yè)面的監(jiān)控因?yàn)轭l繁的陷入會(huì)導(dǎo)致虛擬機(jī)性能的急劇下降。在制定監(jiān)控策略時(shí),應(yīng)當(dāng)避免監(jiān)控這種頁(yè)面。 在實(shí)際應(yīng)用程序運(yùn)行時(shí),例如malloc等動(dòng)態(tài)內(nèi)存申請(qǐng)方法所申請(qǐng)的動(dòng)態(tài)內(nèi)存一般處在應(yīng)用程序的堆棧上,該動(dòng)態(tài)內(nèi)存地址的前后內(nèi)存很有可能也屬于動(dòng)態(tài)內(nèi)存,因此,對(duì)一個(gè)動(dòng)態(tài)內(nèi)存的監(jiān)控,有可能會(huì)附帶監(jiān)控其它多個(gè)動(dòng)態(tài)內(nèi)存,這個(gè)特性對(duì)我們監(jiān)控內(nèi)存的訪問(wèn)是有好處的,因?yàn)橥瑯拥男阅軗p失,完成了對(duì)多個(gè)動(dòng)態(tài)內(nèi)存的監(jiān)控。 為了提高虛擬機(jī)管理器監(jiān)控內(nèi)存的效率,除了避免對(duì)熱頁(yè)面的監(jiān)控,還應(yīng)當(dāng)減小監(jiān)控粒度。對(duì)于頁(yè)面級(jí)的監(jiān)控,4K大小的頁(yè)面要優(yōu)于2M大小的頁(yè)面,因?yàn)樘摂M機(jī)對(duì)前者的訪問(wèn)次數(shù)一般要少于對(duì)后者的訪問(wèn)次數(shù)。如果硬件提供更細(xì)粒度的機(jī)制,應(yīng)當(dāng)優(yōu)先使用硬件提供的機(jī)制。3、在KVM平臺(tái)上的實(shí)現(xiàn) 我們?cè)贙MV-84虛擬機(jī)管理器之上實(shí)現(xiàn)了內(nèi)存泄露的探測(cè)。KVM是基于GNU/Linux實(shí)現(xiàn)的虛擬機(jī)管理器,以模塊的形式運(yùn)行在操作系統(tǒng)中。虛擬機(jī)表現(xiàn)為操作系統(tǒng)中的一個(gè)QEMU/qemu/進(jìn)程,該進(jìn)程通過(guò)和KVM模塊的交互,實(shí)現(xiàn)了處理器虛擬化、內(nèi)存虛擬化以及部分硬件的虛擬化;其它硬件設(shè)備如網(wǎng)卡和外存的虛擬化,由QEMU實(shí)現(xiàn)。因?yàn)镵VM是操作系統(tǒng)內(nèi)部的一個(gè)模塊,所以其調(diào)試和運(yùn)行非常方便,通過(guò)模塊的動(dòng)態(tài)加載和卸除即可實(shí)現(xiàn)更新,這點(diǎn)是Xen[10]無(wú)法提供的,在其上每次修改都需要重啟/qemu/ 本實(shí)驗(yàn)中,虛擬機(jī)使用的操作系統(tǒng)是比較主流的Redhat4.1.1-52版本。接下來(lái)討論實(shí)現(xiàn)中的各個(gè)細(xì)節(jié)問(wèn)題。 申請(qǐng)和釋放函數(shù)地址的獲取。存在于用戶地址空間的函數(shù)例如malloc和free函數(shù),通過(guò)調(diào)試程序例如GDB即可獲取其地址。將應(yīng)用程序的可執(zhí)行代碼進(jìn)行反匯編,也很容易察看到這些函數(shù)的地址。例如在2.3.2小節(jié)中,截獲malloc的調(diào)用,只需要在地址0x804830c處插入VMCALL代碼即可。內(nèi)核函數(shù)如vmalloc和vfree等的地址,可在GNU/Linux的sysmap中獲取。 通過(guò)VMCALL可以將資源申請(qǐng)和釋放的函數(shù)地址傳遞到虛擬機(jī)管理器中。這些地址是有限的、靜態(tài)的。而對(duì)這些函數(shù)的調(diào)用點(diǎn)是在虛擬機(jī)運(yùn)行過(guò)程中動(dòng)態(tài)發(fā)現(xiàn)的,我們需要截獲的調(diào)用返回點(diǎn)因此也是動(dòng)態(tài)的。因?yàn)閷?duì)這些地址(申請(qǐng)和釋放資源的函數(shù)地址、函數(shù)調(diào)用返回點(diǎn))的查找操作非常頻繁,所以我們將這些地址以及陷入點(diǎn)類型等信息存放在快速查找樹(shù)中,以提高查找效率。 對(duì)資源函數(shù)調(diào)用和返回的截獲。在函數(shù)的首地址和返回處插入VMCALL指令之后,虛擬機(jī)會(huì)在這些地址陷入到虛擬機(jī)管理器中。陷入原因是VMCALL。我們?cè)谔幚鞻MCALL時(shí),判斷陷入地址是否在快速查找樹(shù)中,如果在,則查明陷入點(diǎn)的類型。有三種類型:資源申請(qǐng)函數(shù)陷入、資源釋放函數(shù)陷入和返回點(diǎn)陷入。如果陷入點(diǎn)是資源申請(qǐng)函數(shù),則需要分析并記錄其參數(shù),另外在返回點(diǎn)處插入VMCALL。如果陷入點(diǎn)是返回點(diǎn),則需要分析函數(shù)返回結(jié)果。函數(shù)的返回結(jié)果一般存在堆棧上或者寄存器中,不同類型的函數(shù)是不一樣的,需要區(qū)分對(duì)待。如果申請(qǐng)成功,需要記錄動(dòng)態(tài)內(nèi)存的信息:首地址、大小、時(shí)間和類型等。如果陷入點(diǎn)的類型是資源釋放函數(shù),則需要分析其參數(shù),將該動(dòng)態(tài)內(nèi)存的分配記錄刪除。 完成截獲后的分析和記錄,調(diào)用KVM的emulate_instruction函數(shù),模擬執(zhí)行指令,跳過(guò)被插入的VMCALL指令。這里的額外工作是,emulate_instruction函數(shù)會(huì)讀取虛擬機(jī)的指令進(jìn)行模擬,而當(dāng)前指令是被替換過(guò)的VMCALL指令,需要給該函數(shù)提供被替換前的指令。解決方法是修改虛擬機(jī)管理器讀取虛擬機(jī)指令的函數(shù),對(duì)不同情況進(jìn)行判斷,如果讀取指令地址是被我們替換過(guò)的地址,則需要返回原始指令。然后把狀態(tài)從VMM切換到VM,截獲工作至此完成。 函數(shù)調(diào)用棧的獲取。當(dāng)一個(gè)函數(shù)被調(diào)用時(shí),返回地址被壓到棧上,然后處理器跳轉(zhuǎn)到被調(diào)用的函數(shù)處開(kāi)始執(zhí)行。當(dāng)被調(diào)用的函數(shù)返回時(shí),處理器從原來(lái)被壓到棧上的返回地址處繼續(xù)執(zhí)行。當(dāng)程序執(zhí)行的過(guò)程中出現(xiàn)多層調(diào)用時(shí),棧上就會(huì)保存一系列對(duì)應(yīng)的返回地址。由這些返回地址很容易獲取到其所在的一系列函數(shù)。這一系列函數(shù)被稱作調(diào)用棧。資源分配時(shí),分配函數(shù)的調(diào)用棧能夠輔助程序開(kāi)發(fā)人員分析此函數(shù)調(diào)用的代碼軌跡。對(duì)于疑似被泄露的內(nèi)存,通過(guò)其分配函數(shù)的調(diào)用棧可以,獲悉其分配時(shí)程序的上下文,從而排查出其是否真的存在內(nèi)存泄露。 獲取函數(shù)調(diào)用棧的難點(diǎn)在于如何從棧上排查出這些返回地址,因?yàn)镮ntelX86體系結(jié)構(gòu)中,棧上不僅保存著返回地址,還保存著函數(shù)的參數(shù)。準(zhǔn)確地獲取函數(shù)調(diào)用棧需要結(jié)合分析應(yīng)用程序的代碼和堆棧上的數(shù)據(jù),這種方法比較耗時(shí)。本文采用的是應(yīng)用在GNU/Linux內(nèi)核中的方法。該方法逐條讀取堆棧中的數(shù)據(jù),如果該數(shù)據(jù)落在代碼地址空間中,則該數(shù)據(jù)被認(rèn)為是一個(gè)返回地址。在實(shí)際的運(yùn)行過(guò)程中,該方法不僅快,而且正確率高。 在KVM的影子頁(yè)表機(jī)制中實(shí)現(xiàn)對(duì)內(nèi)存的監(jiān)控。實(shí)現(xiàn)過(guò)程需要兩個(gè)步驟。第一,對(duì)于欲監(jiān)控內(nèi)存區(qū)域所跨越的每個(gè)頁(yè),在影子頁(yè)表中清除其PageTableEntry(PTE),使得以后對(duì)這些頁(yè)面的訪問(wèn)會(huì)產(chǎn)生PageFault。因?yàn)槲覀冃薷牧薖TE,改變了GVA到HPA的映射關(guān)系,所以還需要清除TLB,使原來(lái)的映射失效。第二步便是PageFault的處理。在虛擬機(jī)發(fā)生PageFault時(shí),判斷被訪問(wèn)地址是否在我們保護(hù)的范圍內(nèi),甄別出需要額外處理的。對(duì)于被監(jiān)控區(qū)域的訪問(wèn),記錄被訪問(wèn)時(shí)間和類型(讀或?qū)懀?,解除?duì)此內(nèi)存區(qū)域的監(jiān)控。KVM默認(rèn)的處理程序會(huì)為這個(gè)頁(yè)面建立新的PTE,至此監(jiān)控解除。 監(jiān)控策略的實(shí)現(xiàn)。我們將監(jiān)控策略以進(jìn)程的方式運(yùn)行,策略進(jìn)程和虛擬機(jī)模塊通過(guò)命令進(jìn)行數(shù)據(jù)交互,這種實(shí)現(xiàn)方式主要基于如下的考慮。首先,監(jiān)控策略的推斷是一個(gè)復(fù)雜且繁瑣的過(guò)程,不適合實(shí)現(xiàn)在內(nèi)核中,在進(jìn)程中實(shí)現(xiàn)能夠更加靈活。其次,將高層功能從虛擬機(jī)管理器中抽取出來(lái),有利于虛擬機(jī)管理器的穩(wěn)定。監(jiān)控策略的步驟如下:第一步,策略程序向虛擬機(jī)管理器發(fā)送命令,獲取當(dāng)前未被釋放的動(dòng)態(tài)內(nèi)存的信息列表,包括內(nèi)存起始地址、長(zhǎng)度、申請(qǐng)時(shí)間、最后訪問(wèn)時(shí)間、類型以及函數(shù)調(diào)用棧等信息。第二步,策略進(jìn)程從列表中推選出需要監(jiān)控的內(nèi)存段,發(fā)送命令給虛擬機(jī)管理器。最后,策略進(jìn)程匯總內(nèi)存段的各種信息,判斷其是否存在內(nèi)存泄露嫌疑。4、實(shí)驗(yàn)評(píng)估前面介紹了基于虛擬機(jī)管理器探測(cè)內(nèi)存泄露的實(shí)現(xiàn),本節(jié)說(shuō)明探測(cè)內(nèi)存泄露相關(guān)實(shí)驗(yàn)的結(jié)果。我們主要關(guān)注探測(cè)機(jī)制對(duì)虛擬機(jī)帶來(lái)的性能損失和內(nèi)存探測(cè)有效性兩個(gè)方面。針對(duì)各部分實(shí)驗(yàn)結(jié)果,分析了原因,并指出了可能的改進(jìn)辦法。最終實(shí)驗(yàn)結(jié)果表明,基于虛擬機(jī)管理器進(jìn)行內(nèi)存泄露的探測(cè),其實(shí)現(xiàn)對(duì)應(yīng)用程序造成的性能損失很小,低于10%。在公認(rèn)的存在內(nèi)存泄露的開(kāi)源項(xiàng)目中,發(fā)現(xiàn)了內(nèi)存泄露的嫌疑。因?yàn)槭艿綔y(cè)試程序的限制,所發(fā)現(xiàn)的內(nèi)存泄露嫌疑比較有限,如果將應(yīng)用程序部署在真實(shí)的應(yīng)用環(huán)境中,將會(huì)有更佳的結(jié)果。4.1實(shí)驗(yàn)環(huán)境我們使用的測(cè)試環(huán)境為,IntelCore?2CPU@1.86GHz,雙核CPU,2MCache,2G內(nèi)存;KVM-84版本,虛擬機(jī)中內(nèi)核版本為L(zhǎng)inux,只配備了一個(gè)硬盤分區(qū)。SATA硬盤,單網(wǎng)卡。編譯器為GCC4.1.1。虛擬機(jī)管理器所在的操作系統(tǒng)版本也是Linux。每次測(cè)試時(shí)除了受測(cè)試虛擬機(jī)運(yùn)行外,無(wú)其他虛擬機(jī)在執(zhí)行。虛擬機(jī)只配備了一個(gè)VCPU(VirtualCPU)。首先,我們測(cè)試了本實(shí)現(xiàn)對(duì)虛擬機(jī)性能的影響;然后,測(cè)試了公認(rèn)的存在內(nèi)存泄露的開(kāi)源項(xiàng)目中,內(nèi)存分配和釋放的情況,并分析了內(nèi)存泄露的嫌疑。4.2性能損失測(cè)試我們?cè)O(shè)計(jì)了兩個(gè)實(shí)驗(yàn),測(cè)試了本實(shí)現(xiàn)本身對(duì)運(yùn)行在KVM之上的應(yīng)用程序性能的影響。實(shí)驗(yàn)一測(cè)試的程序是常見(jiàn)的編譯器GCC4.1.1,我們截獲了GCC中的所有的內(nèi)存申請(qǐng)和釋放函數(shù)調(diào)用,然后分別測(cè)試了編譯proftpd-1.3.2rc4源代碼的時(shí)間;實(shí)驗(yàn)二是我們?cè)O(shè)計(jì)的程序,該程序調(diào)用了6億次的malloc和free函數(shù)。最終結(jié)果如表1所示。表1應(yīng)用程序在虛擬機(jī)中的性能對(duì)比KVM-84KVM-84-memory-leak-detectionGCC4.1.128秒30秒6億次調(diào)用malloc和free68.889秒69.083秒由表1可知,具有異常頻繁內(nèi)存申請(qǐng)和釋放的GCC4.1.1程序,在正常的KVM虛擬機(jī)上編譯一個(gè)應(yīng)用程序所需時(shí)間為28秒,而在添加了內(nèi)存泄露探測(cè)機(jī)制的KVM虛擬機(jī)上編譯同一個(gè)應(yīng)用程序所需時(shí)間為30秒,可見(jiàn)內(nèi)存泄露探測(cè)機(jī)制引起的性能損失在10%以內(nèi)。而對(duì)于我們?cè)O(shè)計(jì)的6億次malloc和free函數(shù)調(diào)用的程序,內(nèi)存泄露探測(cè)機(jī)制引起的性能損失則更少,幾乎可以忽略不計(jì)。4.3有效性為了測(cè)試基于虛擬機(jī)管理器進(jìn)行內(nèi)存泄露機(jī)制的有效性,我們找到了公認(rèn)存在內(nèi)存泄露的兩個(gè)開(kāi)源項(xiàng)目:proftpd-1.2.9和squid-2.4,并對(duì)其分別進(jìn)行了測(cè)試。測(cè)試proftpd-1.2.9的實(shí)驗(yàn)環(huán)境是:通過(guò)多個(gè)客戶端程序,向服務(wù)器發(fā)送1000次SIZE命令。因?yàn)镾IZE命令會(huì)導(dǎo)致proftpd發(fā)生內(nèi)存泄露。在測(cè)試程序完成后,尚未被proftpd釋放的動(dòng)態(tài)內(nèi)存詳細(xì)信息見(jiàn)表2。表2proftpd中未釋放內(nèi)存片段的詳細(xì)信息申請(qǐng)內(nèi)存的IP地址調(diào)用函數(shù)類型調(diào)用次數(shù)申請(qǐng)內(nèi)存的長(zhǎng)度(字節(jié))0x804e559malloc()29不統(tǒng)一0x804e778malloc()180x8051239malloc()35絕大部分是5240x80584f8realloc()14097從表2中我們可以看出,在IP地址0x804e778和0x80584f8處只有一次沒(méi)有釋放的malloc內(nèi)存分配,分配的內(nèi)存長(zhǎng)度分別為8個(gè)字節(jié)和4097個(gè)字節(jié);而在IP地址0x804e559和0x8051239處沒(méi)有釋放的malloc分配記錄則有數(shù)十次,并且在IP地址0x8051239處分配的內(nèi)存長(zhǎng)度絕大部分都是相同的,因此我們可以推測(cè)此處很有可能是一個(gè)內(nèi)存泄露點(diǎn)。測(cè)試squid-2.4的方法是同時(shí)啟動(dòng)5個(gè)客戶端程序,每個(gè)程序向squid服務(wù)連續(xù)發(fā)送100個(gè)請(qǐng)求。在5個(gè)客戶端程序都結(jié)束時(shí),squid服務(wù)未釋放的動(dòng)態(tài)內(nèi)存資源見(jiàn)表3。表3squid中未釋放內(nèi)存片段的詳細(xì)信息申請(qǐng)內(nèi)存的IP地址調(diào)用函數(shù)類型調(diào)用次數(shù)申請(qǐng)內(nèi)存的長(zhǎng)度(字節(jié))0x80a8e4acalloc()113不統(tǒng)一0x80a8f88malloc()14640x80a8edfrealloc()2192 從表3中我們可以看出,在IP地址0x80a8e4a處有上百次的calloc分配都沒(méi)有釋放,它很有可能是一個(gè)內(nèi)存泄露點(diǎn);在IP地址0x80a8f88處有14次malloc內(nèi)存分配沒(méi)有釋放,且分配的內(nèi)存長(zhǎng)度都是64字節(jié),它也可能是一個(gè)內(nèi)存泄露點(diǎn);而在IP地址0x80a8edf處只有兩次realloc內(nèi)存分配沒(méi)有釋放。如表2和表3所示,存在內(nèi)存泄露的可能IP地址是非常有限的,通過(guò)函數(shù)調(diào)用棧,調(diào)試人員很容易就能夠定位存在內(nèi)存泄露的點(diǎn)。正如上面所說(shuō),proftpd測(cè)試中,SIZE命令必然會(huì)導(dǎo)致內(nèi)存泄露,所以在表2中的IP地址中,必然存在內(nèi)存泄露。5、結(jié)論以及下一步工作 虛擬機(jī)技術(shù)的不斷發(fā)展使得虛擬化的代價(jià)越來(lái)越低,同時(shí)也推動(dòng)了虛擬化技術(shù)的應(yīng)用。利用虛擬化技術(shù)來(lái)提高操作系統(tǒng)的安全性一直以來(lái)受到人們?cè)絹?lái)越多的重視?;谔摂M化平臺(tái)已經(jīng)有了一系列的研究。其中一項(xiàng)是利用虛擬機(jī)的可復(fù)制性建立HoneyFarm[11],以捕獲、記錄和分析黑客對(duì)系統(tǒng)的攻擊行為,從而提高系統(tǒng)的安全性。另外,Lycosid[12]利用虛擬機(jī)管理器對(duì)資源的絕對(duì)控制和對(duì)操作系統(tǒng)的透明性,提出了一套檢測(cè)和標(biāo)識(shí)隱藏進(jìn)程的機(jī)制;有很多病毒程序能夠在操作系統(tǒng)中隱藏自己,增加被用戶發(fā)現(xiàn)的難度。本文利用虛擬機(jī)管理器對(duì)其上虛擬機(jī)的掌控性和透明性,提出了探測(cè)內(nèi)存泄露的一種機(jī)制,該機(jī)制提供了內(nèi)存探測(cè)的平臺(tái)通用性,不需要修改或者重新編譯應(yīng)用程序的源代碼,并且,虛擬機(jī)的性能損失在10%以內(nèi)。 本文的基本思路是:在虛擬機(jī)平臺(tái)中通過(guò)在虛擬機(jī)(GuestOS)中插入指令的方式,透明地?cái)r截應(yīng)用程序申請(qǐng)和釋放內(nèi)存資源的函數(shù)調(diào)用,例如malloc等動(dòng)態(tài)內(nèi)存申請(qǐng)函數(shù)和釋放動(dòng)態(tài)內(nèi)存的free函數(shù),或者Linux內(nèi)核的vmalloc和vfree函數(shù),維護(hù)應(yīng)用程序所使用動(dòng)態(tài)內(nèi)存資源的列表。因?yàn)楸恍孤兜膬?nèi)存不會(huì)被應(yīng)用程序所訪問(wèn),所以接下來(lái)需要從這個(gè)列表中推選出一部分,進(jìn)行訪問(wèn)的監(jiān)控。那些長(zhǎng)時(shí)間不被釋放且不被訪問(wèn)的內(nèi)存資源,則是很好的內(nèi)存泄露的嫌疑。為了減少監(jiān)控內(nèi)存訪問(wèn)的性能損失,本文作了一些重要的優(yōu)化,例如放棄對(duì)熱頁(yè)面的監(jiān)控。 本研究發(fā)現(xiàn),利用虛擬化技術(shù)探測(cè)內(nèi)存泄露具有可行性。首先是在線性,根據(jù)實(shí)驗(yàn),利用虛擬機(jī)管理器探測(cè)內(nèi)存泄露給虛擬機(jī)帶來(lái)的性能損失小于10%。測(cè)試程序的邏輯是有限的,有些內(nèi)存泄露只有在真正應(yīng)用時(shí)才能發(fā)現(xiàn)。其次是有效性,通過(guò)實(shí)驗(yàn),在公認(rèn)的存在內(nèi)存泄露的開(kāi)源項(xiàng)目中,確實(shí)能夠發(fā)現(xiàn)內(nèi)存泄露的嫌疑。另外的優(yōu)勢(shì)是通用性,該方法不僅適用于GNU/Linux操作系統(tǒng),而且對(duì)Windows也使用,不僅適用于用戶程序,對(duì)操作系統(tǒng)內(nèi)核也同樣適用。最后是實(shí)現(xiàn)的簡(jiǎn)單性,該方法不需要修改現(xiàn)有的操作系統(tǒng),只需要對(duì)支撐虛擬機(jī)運(yùn)行的虛擬機(jī)管理器進(jìn)行修改。 我們下一步工作是,在虛擬機(jī)之內(nèi)確認(rèn)內(nèi)存泄露之后,通過(guò)動(dòng)態(tài)代碼修補(bǔ)的技術(shù),動(dòng)態(tài)修正運(yùn)行在虛擬機(jī)中的應(yīng)用程序,以保證應(yīng)用程序所提供的服務(wù)不會(huì)中止。

參考文獻(xiàn)YichenXieandAlexAiken.Context-andPath-sensitiveMemoryLeakDetection,InProceedingsofESEC/FSE2021,Lisbon,Portugal.TsaiT.,VaidyanathanK.,GrossK.Low-OverheadRun-TimeMemoryLeakDetectionandRecovery,PRDC’06,2021.RationalPurify.Purify:FastDetectionofMemoryLeaksandAccessErrors.

/software/awdtools/purify/FengQin,ShanLuandYuanyuanZhou.SafeMem:ExploitingECC-MemoryforDetectingMemoryLeaksandMemoryCorruptionduringProductionRuns,HPCA’05,2021.PrashanthP.BungaleandChi-KeungLuk.PinOS:AProgrammableFrameworkforWhole-SystemDynamicInstrumentation,InACMConferenceonVirtualExecutionEnvironments(VEE’07),2021.CarlA.Waldspurger.MemoryResourceManagementinVMwareESXServer.ProceedingsofFifthSymposiumonOperatingSystemsDesignandImplementation(OSDI),2021.P.Barham,B.Dragovic,K.Fraser,S.Hand,T.Harris,A.Ho,R.Neugebauery,I.Pratt,andA.Wareld.XenandtheArtofVirtualization,inProceedingsofthe19thACMSymposiumonOperatingSystemPrinciples(SOSP'03),ACM,2021.Intel.Intel?VirtualizationTechnology:Hardwaresupportforefficientprocessorvirtualization,Intel.AMD.AMD-V?NestedPaging,IssueDate:July,2021,Revision:1.0.PaulBarham,BorisDragovic,KeirFraser,StevenHand,TimHarris,AlexHo,RolfNeugebauer,IanPratt,AndrewWar?eld.XenandtheArtofVirtualization,SOSP’03,2021.MichaelVrable,JustinMa,JayChen,DavidMoore,ErikVandekieft,AlexC.Snoeren,GeoffreyM.Voelker,andStefanSavage.Scalability,Fidelity,andContainmentinthePotemkinVirtualHoneyfarm,SOSP’05,2021.S.T.Jones,A.C.Arpaci-Dusseau,andR.H.Arpaci-Dusseau.VMM-basedhiddenprocessdetectionandidentificationusingLycosid,InACMConferenceonVirtualExecutionEnvironments(VEE’08),Seattle,WA,Mar.2021.

DetectingMemoryLeakviaVMMWANGXiaolin1,WANGZhenlin2,SUNYifeng1,LIUYi1,ZHANGBinbin1,LUOYingwei11)SchoolofElectronicsEngineeringandComputerScience,PekingUniversity,Beijing,1008712)Dept.ofComputerScience,MichiganTechnologicalUniversity,Houghton,MI49931,USAAbstract:Inthispaper,virtualizationtechnologyisutilizedtotransparentlyrecordtheallocationandreleaseofmemoryresourcesappliedbyapplicationsrunningonvirtualmachine(VM),andtheserecordsprovidetheauxiliaryinformationtodetectmemoryleakshidinginthebinarycode.Firstly,thismechanismdoesnotrequiresourcecodemodificationorrecompilation;secondly,theperformanceoverheadisverysmall,whichmakesitpossibletobuildonlinememoryleakdetectionandreportingmechanisms,freeapplicationdevelopersfromdesigningtestsuiteandimprovethechancesoffindingmorememoryleaks.Besides,memoryleakdetectionbasedonthevirtualenvironmentalsoprovidesversatilitywithoutneedingspecialhardwaresupports:notonlyuser-modeapplicationcanbedetected,buttheoperatingsystemkernel;andbothLinuxandWindowsaresupported.Existingresearchcannotbringallofthesefeaturestogether.Theexperimentalresultsshowthat:ourmemoryleakdetectionmechanismhasalimitedperformanceoverheadwhichislessthan10%,andtheinformationproducedbythemechanismcanhelpprogrammertotrackoutthepossiblememoryleaksefficiently.Keywords:MemoryLeakDetection;VirtualMachine;VirtualizationPlatform;VirtualMachineMonitor

工作背景及聲明 本文研究的問(wèn)題屬于面向執(zhí)行碼的軟件分析、運(yùn)行時(shí)軟件分析與驗(yàn)證以及軟件分析實(shí)踐與產(chǎn)業(yè)應(yīng)用。目前,基于虛擬機(jī)管理器的軟件分析正在初步開(kāi)展,在保證性能、復(fù)雜性以及平臺(tái)通用性方面尚有很大的研究潛力。本文旨在通過(guò)虛擬機(jī)管理器,提供一種在線的通用內(nèi)存泄露檢測(cè)機(jī)制。本研究基于國(guó)家973計(jì)劃項(xiàng)目(2021CB310900)計(jì)算系統(tǒng)虛擬化基礎(chǔ)理論與方法研究的課題2(2021CB310902)單計(jì)算系統(tǒng)虛擬化方法研究。該項(xiàng)目致力于提高國(guó)內(nèi)虛擬化技術(shù)的研究水平。本研究組的研究涵蓋了虛擬機(jī)在線遷移、虛擬機(jī)在線復(fù)制、虛擬機(jī)遠(yuǎn)程內(nèi)存共享訪問(wèn)、動(dòng)態(tài)半虛擬化技術(shù)以及虛擬機(jī)安全,已經(jīng)在國(guó)際期刊和會(huì)議論文中發(fā)表文章9篇,包括VEE、IEEECluster、ISCAWorkshop、SCWorkshop以及HPCC,和國(guó)內(nèi)期刊例如中國(guó)科學(xué)和電子學(xué)報(bào)等發(fā)表學(xué)術(shù)文章多篇。本文的題目屬于虛擬機(jī)安全的范圍。 聲明:稿件內(nèi)容屬于作者的科研成果;署名無(wú)爭(zhēng)議;引用他人成果已注明出處;未公開(kāi)發(fā)表過(guò)。

論大學(xué)生寫作能力寫作能力是對(duì)自己所積累的信息進(jìn)行選擇、提取、加工、改造并將之形成為書面文字的能力。積累是寫作的基礎(chǔ),積累越厚實(shí),寫作就越有基礎(chǔ),文章就能根深葉茂開(kāi)奇葩。沒(méi)有積累,胸?zé)o點(diǎn)墨,怎么也不會(huì)寫出作文來(lái)的。寫作能力是每個(gè)大學(xué)生必須具備的能力。從目前高校整體情況上看,大學(xué)生的寫作能力較為欠缺。一、大學(xué)生應(yīng)用文寫作能力的定義那么,大學(xué)生的寫作能力究竟是指什么呢?葉圣陶先生曾經(jīng)說(shuō)過(guò),“大學(xué)畢業(yè)生不一定能寫小說(shuō)詩(shī)歌,但是一定要寫工作和生活中實(shí)用的文章,而且非寫得既通順又扎實(shí)不可。”對(duì)于大學(xué)生的寫作能力應(yīng)包含什么,可能有多種理解,但從葉圣陶先生的談話中,我認(rèn)為:大學(xué)生寫作能力應(yīng)包括應(yīng)用寫

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論