下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、 嵌入式系統(tǒng)設(shè)計中消除內(nèi)存丟失的策略 嵌入式系統(tǒng)設(shè)計中消除內(nèi)存丟失的策略 類別:嵌入式系統(tǒng) 在嵌入式系統(tǒng)設(shè)計過程中,許多軟件工程師受困于動態(tài)內(nèi)存管理。本文介紹一種將堆棧中的內(nèi)存碎片降至最少的解決方案,其中講到了內(nèi)存碎片和內(nèi)存丟失的區(qū)別,以及一種在編程中有利于檢測并消除內(nèi)存丟失的策略。 標(biāo)準(zhǔn)C庫函數(shù)malloc()和free()可在任意的時間段中,為應(yīng)用分配任意大小的內(nèi)存塊。隨著內(nèi)存塊的使用
2、和釋放,在整個內(nèi)存區(qū)域中,分配給堆棧的存儲區(qū)將混雜著許多正在使用或已經(jīng)釋放的存儲塊,而未被使用的任何小塊內(nèi)存區(qū)將變得無法使用。例如,某個應(yīng)用要求堆棧分配30字節(jié),如果堆棧中只有20個長度為3字節(jié)的小存儲塊(總共為60字節(jié)),那么堆棧仍然無法為該應(yīng)用分配內(nèi)存,因?yàn)樗璧?0字節(jié)必須是連續(xù)的。 在執(zhí)行時間較長的程序中,內(nèi)存碎片可能導(dǎo)致系統(tǒng)的內(nèi)存枯竭,盡管分配的內(nèi)存總量并未超出總的可用內(nèi)存總數(shù)。內(nèi)存碎片的數(shù)量取決于堆棧的實(shí)現(xiàn)策略。大多數(shù)程序員均采用由編譯器提供的malloc()和free()函數(shù)創(chuàng)建的堆棧,因此內(nèi)存碎片就不受程序員的控制。 內(nèi)存丟失是應(yīng)用程序的缺陷,更具體地,內(nèi)存丟失是一塊已經(jīng)分配但
3、永遠(yuǎn)不會被釋放的內(nèi)存區(qū)。如果所有指向內(nèi)存塊的指針超出界限或者指向其他的區(qū)域,那么應(yīng)用程序?qū)⒂肋h(yuǎn)不能釋放那塊內(nèi)存區(qū)。對于將會在某時刻退出的桌面應(yīng)用程序,較小的內(nèi)存丟失還可以承受,因?yàn)橥顺鲞M(jìn)程將把占用的所有內(nèi)存返還給操作系統(tǒng)。但對于長時間運(yùn)行的嵌入式系統(tǒng),則通常需要確保絕對沒有內(nèi)存丟失。 避免內(nèi)存丟失不是輕而易舉的,為了確保所有分配的內(nèi)存都在隨后釋放,必須建立一套明確的規(guī)則,以確定哪個應(yīng)用占用了內(nèi)存。為跟蹤內(nèi)存,可采用類、指針數(shù)組或鏈表。由于在動態(tài)內(nèi)存分配中,程序員無法預(yù)先知道在給定時間內(nèi)需要分配多少數(shù)據(jù)塊,因此通常需要采用鏈表結(jié)構(gòu)。 例如,假定一個任務(wù)正在接收來自通信信道的消息,任務(wù)將為消息分配
4、空間,而該空間在消息得到完整的處理之前不會被釋放。因?yàn)橄⒂锌赡懿粫凑战邮盏捻樞蜻M(jìn)行處理,因此一些消息存在的時間將比其他消息更長。所有掛起的消息存在于一個列表中,列表的長度取決于任意給定時間內(nèi)進(jìn)行處理的消息數(shù)目。嵌入式系統(tǒng)必須將消息轉(zhuǎn)發(fā)至另外的設(shè)備,而且消息在收到傳送確認(rèn)之前不能被刪除。由于消息將傳送至許多不同的目的地,而且某些目的地可能存在一些導(dǎo)致重傳的故障,因此不能以先入先出方式處理這些消息。 在上述問題中,動態(tài)內(nèi)存管理對RAM的利用效率高于預(yù)定義緩存管理。當(dāng)內(nèi)存不再被消息隊(duì)列使用時,就能被其他隊(duì)列或完全不同的程序部分使用。 當(dāng)多個指針同時指向某個特定的內(nèi)存塊時,通常還會產(chǎn)生另一個特殊問
5、題。如果第一個實(shí)體(entity)占有內(nèi)存并希望釋放該內(nèi)存,那么必須考慮是否還有其他指針指向該區(qū)域。如果存在,那么隨著第一個實(shí)體釋放內(nèi)存,其他的指針將成為懸掛指針(dangling pointer),即該指針指向的空間不再有效。當(dāng)使用懸掛指針時,或許仍然可以得到正確的數(shù)據(jù),但這些內(nèi)存終將被重新使用(通過另一個malloc()調(diào)用),從而導(dǎo)致在懸掛指針和該內(nèi)存的新使用者之間出現(xiàn)不期望的相互影響。 懸掛指針與內(nèi)存丟失剛好相反。如果沒有釋放內(nèi)存,就可能導(dǎo)致內(nèi)存丟失;而如果釋放了那些并不準(zhǔn)備釋放的內(nèi)存則將產(chǎn)生懸掛指針。 內(nèi)存丟失在許多方面與競爭條件非常相似。內(nèi)存丟失引發(fā)的性能失常完全不同于程序錯誤,因
6、此,這些問題很難通過調(diào)試器對代碼進(jìn)行單步調(diào)試加以解決。對于內(nèi)存丟失和競爭條件,代碼檢查有時能比采用任何技術(shù)解決方案更快地找到問題所在。 添加調(diào)試代碼并生成輸出通常比源代碼調(diào)試器更為有效,但在某些競爭條件下,則有可能改變代碼的執(zhí)行特性,從而掩蓋了問題。在內(nèi)存丟失中,添加調(diào)試代碼可改變內(nèi)存配置,這意味著懸掛指針故障可能具有不同的執(zhí)行特性。另一缺陷在于,如果調(diào)試代碼消耗了內(nèi)存,那么調(diào)試版將比產(chǎn)品版更快地耗盡RAM,內(nèi)存丟失就是內(nèi)存丟失,而不管這些調(diào)試代碼的副作用如何,都應(yīng)當(dāng)可被檢測。 驅(qū)動自動碎片收集 Java具有對無用存儲單元進(jìn)行碎片收集(garbage collection)的自動內(nèi)存管理機(jī)制,
7、因此Java程序員無須擔(dān)心內(nèi)存分配的釋放。如果以前曾用過Java進(jìn)行編程,那么與其他編程語言相比,無疑會對Java跟蹤內(nèi)存所需的時間留下深刻的印象。 在Java中,只需犧牲運(yùn)行時間即可換來編程的簡化,因?yàn)槭止す芾韮?nèi)存可以得到更為有效的實(shí)現(xiàn)方法。但當(dāng)程序變得越來越大,手工管理就變得無能為力了。雖然好的手工管理通常能使堆棧的總長度降至最小,但這并不總是輕而易舉的。在那些通常由數(shù)十名程序員完成的大型程序中,人為錯誤將引入足以降低性能等級的大量內(nèi)存丟失,這時就需要自動碎片收集解決方案。 page 在對無用存儲單元進(jìn)行自動碎片收集過程中,一個優(yōu)秀的程序員或許做得遠(yuǎn)比自動碎片收集器出色,但在需要眾多程序員
8、參與的大型項(xiàng)目中,則幾乎不可能找到并修正所有的內(nèi)存丟失。選擇自動系統(tǒng)或許要求對性能進(jìn)行折衷,而且自動碎片收集器有時也會出現(xiàn)混亂。Dobb博士在 網(wǎng)站的“Java Q&A”上列出了許多靈活利用Java進(jìn)行無用存儲單元收集的方法。 盡管自動碎片收集對超大型程序的吸引力日益增強(qiáng),但大多數(shù)嵌入式開發(fā)人員開發(fā)的系統(tǒng)并沒有那么復(fù)雜。而在這些開發(fā)中,只有極少數(shù)開發(fā)人員需要接入包含無用存儲單元自動碎片收集的編程環(huán)境,如Perl、Smalltalk或Java,因此大多數(shù)開發(fā)人員需要知道如何在采用malloc()和free()的C程序或采用new和delete的C+程序中跟蹤內(nèi)存丟失。 檢測工具 查找內(nèi)存
9、丟失的工具很多,最常用的釋放工具就是dmalloc和mpatrol,這些工具提供了記錄并檢查所有內(nèi)存分配的調(diào)試版堆棧,從而有利于分析內(nèi)存丟失和懸掛指針。dmalloc和許多類似的庫還為malloc()和free()提供了一些不同情形下的替代形式。 在許多項(xiàng)目中,我負(fù)責(zé)跟蹤內(nèi)存丟失并提供所有內(nèi)存丟失均已消除的證明。最初,我假定上面提及的一種工具可解決我的問題。然而,實(shí)際發(fā)現(xiàn)malloc()和free()的一種完全替代并不總是適用于嵌入式系統(tǒng)。例如,軟件工程師可能對當(dāng)前的實(shí)現(xiàn)相當(dāng)滿意,而只想簡單地添加一些監(jiān)控功能。如果選擇了替代malloc()和free()的庫,那么就不得不移植這些例行程序。 因
10、為可用的自由庫是面向Unix的,因而可通過調(diào)用sbrk()從操作系統(tǒng)獲取內(nèi)存塊。有些操作系統(tǒng)中并沒有這個調(diào)用(甚至實(shí)際上都沒有操作系統(tǒng))。在移植時,對于特定的處理器必須提及諸如指針大小和內(nèi)存對齊這樣的問題。本文用的編譯器庫中的malloc()和free()已經(jīng)解決了這些問題,即編譯器庫已完全移植到正在使用的處理器上,因此希望避免這樣的重復(fù)工作。對調(diào)試版malloc()和free()進(jìn)行移植的另一問題在于,調(diào)試版通常假定可以將分析數(shù)據(jù)存入一個文件中。但本文工作的系統(tǒng)通常并不包含任何有效的文件系統(tǒng),因此必須限制存儲到只帶有最少資源的設(shè)備上的數(shù)據(jù)量。 我也曾考慮利用現(xiàn)有的工具在臺式機(jī)上運(yùn)行部分代碼。
11、Compuware公司的Bounds Checker就是這樣的工具,該工具專門針對窗視操作系統(tǒng),但在特殊情形下,本文用的代碼是標(biāo)準(zhǔn)的ANSI C,因此可以簡單地在PC上進(jìn)行編譯并結(jié)合Bounds Checker庫運(yùn)行。Bounds Checker工具也將檢查Win32 API的諸多部分,但只對堆棧分配感興趣。 結(jié)果是讓人失望的,Bounds Checker面臨的最大障礙就在于該工具必須在程序退出后才能遞交報告。在程序退出之前尚未釋放的數(shù)據(jù)將被視為內(nèi)存丟失。盡管這是一個合理定義,但并不適用于我的應(yīng)用程序,因?yàn)榕cPC應(yīng)用程序不同,嵌入式程序通常無需退出。 我用的代碼包含一個連續(xù)執(zhí)行的循環(huán),為實(shí)現(xiàn)本
12、測試的目的,可以在循環(huán)的末尾添加一些校驗(yàn),以人為地退出程序。但不釋放所有的內(nèi)存資源而中斷程序?qū)?dǎo)致Bounds Checker指示所有正在使用的內(nèi)存此時正發(fā)生丟失。大多數(shù)內(nèi)存只是簡單地等待,以便在下一次循環(huán)中重新得到使用。只需要編寫一個釋放所有內(nèi)存的退出程序段,就能使Bounds Checker獲得更好的性能,但這樣的程序段無法在實(shí)時系統(tǒng)中運(yùn)行并將掩蓋實(shí)際存在的問題。 由此可以得到如下結(jié)論:一旦明確了哪行代碼存在疑問,就能用Bounds Checker標(biāo)識出特定內(nèi)存丟失的精確來源,因此要關(guān)注Bounds Checker的整體性能。 假定隨著程序的運(yùn)行,緩存鏈表數(shù)將增大或減少。因?yàn)殒湵砜墒钩绦蛘?/p>
13、到每個緩存,因此可以在任意時間釋放所有的緩存。如果程序存在漏洞,使一個應(yīng)當(dāng)移除并釋放的緩存仍然留在鏈表中,那么鏈表將無限增長。如果程序刪除整個鏈表,那么漏洞的痕跡將消失得無影無蹤,而鏈表重新開始記錄。在需要運(yùn)行很長時間的系統(tǒng)中,鏈表最終將變得很大,直到耗盡所有的內(nèi)存。 即便采用無用存儲自動碎片收集器管理內(nèi)存,類似的漏洞仍將成為障礙,因?yàn)閲?yán)格地講,額外的緩存并不是內(nèi)存丟失,它們?nèi)钥梢允栈?。為解決這類問題,我們希望確定總的內(nèi)存使用率是否正在增加,而不管這些內(nèi)存是否已經(jīng)釋放,或者是否可能釋放這些內(nèi)存。 內(nèi)存使用率的測量 如果需要修改malloc(),理想情況下應(yīng)當(dāng)采用不同的名稱取代所有的malloc
14、()調(diào)用。我將其取名為mmalloc(),意即“measured malloc”。這樣我們就能編寫一個執(zhí)行一些額外工作并調(diào)用常規(guī)malloc()的函數(shù),這也可以通過其他途徑實(shí)現(xiàn),如采用#define取代malloc(),或在編譯庫中利用鏈接程序重命名malloc()函數(shù)。 這種方法的一個缺陷在于,不能對從我無法更改或重新編譯的庫函數(shù)中調(diào)用的malloc()進(jìn)行監(jiān)控。例如,標(biāo)準(zhǔn)庫包含一個依次調(diào)用malloc()的函數(shù)strdup(),我們無法用malloc()調(diào)用加以取代,除非我們擁有正在使用的庫的源代碼。 測量使用率的第一步是簡單地添加需要分配的內(nèi)存并減去任何已經(jīng)釋放的內(nèi)存。對于malloc(),這當(dāng)然微不足道。假定定義了一個靜態(tài)值G_inUse,那么下面的代碼就能跟蹤內(nèi)存的分配: = void *mmalloc(size_t size) G_inUse += size; return malloc(size); = mfree()略微復(fù)雜一些,因?yàn)閒ree()并不傳遞表示內(nèi)存大小的變量。函數(shù)free()傳遞指向內(nèi)存塊的指針。通常表示釋放內(nèi)存大小的量隱藏在指針?biāo)赶驍?shù)據(jù)塊之前的數(shù)據(jù)頭中,所以可以得到下面的函數(shù): = void mfree(void *p) size_t *sizePtr=(size_t *) p)-1; G_inUse -= *sizePtr; free(p);
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度文化展覽館租賃合同·含策展服務(wù)及觀眾導(dǎo)覽3篇
- 二零二五年度房屋租賃合同:安全責(zé)任與租戶培訓(xùn)2篇
- 2025年度物聯(lián)網(wǎng)通信平臺建設(shè)與運(yùn)營合同3篇
- 2025年度綠色節(jié)能施工合同終止及效益協(xié)議3篇
- 二零二五年度智慧城市建設(shè)服務(wù)合同標(biāo)的規(guī)劃與實(shí)施3篇
- 二零二五年度文化產(chǎn)業(yè)發(fā)展股權(quán)讓渡與債務(wù)抵消合同3篇
- 二零二五年度智慧城市基礎(chǔ)設(shè)施建設(shè)項(xiàng)目合同6篇
- 二零二五年度建筑設(shè)計創(chuàng)意版權(quán)轉(zhuǎn)讓協(xié)議2篇
- 海南職業(yè)技術(shù)學(xué)院《鋼結(jié)構(gòu)設(shè)計課程設(shè)計》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025版黃金抵押擔(dān)保供應(yīng)鏈融資合同3篇
- 中圖版八年級地理下冊6.2《中東》練習(xí)題(含答案)
- “基礎(chǔ)教育精品課”PPT課件模板
- 公司8D異常報告
- 職業(yè)教育技能大賽存在的問題及建議
- 2022屆高考英語二輪復(fù)習(xí):閱讀理解細(xì)節(jié)理解題 導(dǎo)學(xué)案
- 中文網(wǎng)絡(luò)成癮量表(臺灣陳淑惠)
- 儲運(yùn)車間裝卸車和儲罐安全操作培訓(xùn)
- 洞庭湖觀鳥旅游發(fā)展現(xiàn)狀及對策
- 土壤與肥料學(xué)課件
- 供應(yīng)商物料質(zhì)量問題賠償協(xié)議(中文)
- 集團(tuán)公司員工宿舍管理辦法(正式版)
評論
0/150
提交評論