IEC 61508標(biāo)準(zhǔn)強(qiáng)烈推薦使用靜態(tài)內(nèi)存管理方式。在安全應(yīng)用設(shè)計(jì)中,我們都在遵循這個(gè)建議。但我們可能會(huì)需要這樣的功能:
? 運(yùn)行時(shí)配置
? 刪除組件的編譯時(shí)配置
? 更靈活的控制外部行為或硬件
? 平臺(tái)作為完整的一代產(chǎn)品
這些功能需要?jiǎng)討B(tài)內(nèi)存管理解決方案。
IEC61508中推薦使用靜態(tài)內(nèi)存管理方式的原因與動(dòng)態(tài)內(nèi)存管理相關(guān)的編程錯(cuò)誤導(dǎo)致的潛在風(fēng)險(xiǎn)相關(guān),我們必須避免和發(fā)現(xiàn)這些編程錯(cuò)誤,潛在風(fēng)險(xiǎn)包括:
1 內(nèi)存碎片
2 沒有可用內(nèi)存
3 空閑內(nèi)存丟失
4 內(nèi)存釋放到錯(cuò)誤內(nèi)存池
5 內(nèi)存多次釋放
6 釋放后繼續(xù)使用內(nèi)存
7 使用時(shí)釋放內(nèi)存
一類解決方案只允許分配內(nèi)存,這類解決方案通過避免內(nèi)存重用來解決上述問題中的3-7,這是一種有效的解決方案,通常用于不同產(chǎn)品變體啟動(dòng)期間中的內(nèi)存靈活配置,在運(yùn)行期間保持內(nèi)存布局不變。
當(dāng)這類方法不能滿足需求時(shí),我們需要一種更通用的方法來系統(tǒng)地避免或檢測(cè)所有列出的風(fēng)險(xiǎn)情況。
1內(nèi)存碎片
內(nèi)存碎片是一種效應(yīng),當(dāng)我們使用不同的內(nèi)存大小執(zhí)行多個(gè)分配和釋放周期時(shí)可能會(huì)產(chǎn)生這種效應(yīng)。
在實(shí)時(shí)系統(tǒng)中,我們需要確定性和恒定的執(zhí)行時(shí)間。使用改進(jìn)的分配算法(如首次適配算法),執(zhí)行時(shí)間嚴(yán)重將依賴于以前的內(nèi)存活動(dòng),這對(duì)我們的系統(tǒng)設(shè)計(jì)是不利的。
避免內(nèi)存碎片的方法是使用一個(gè)(或一組)固定大小的內(nèi)存塊池。好消息是專業(yè)的實(shí)時(shí)內(nèi)核為用戶提供了固定大小內(nèi)存塊的內(nèi)存管理機(jī)制,用戶可以使用實(shí)時(shí)內(nèi)核提供的這些服務(wù)。在本文中,我們考慮實(shí)時(shí)內(nèi)核的主函數(shù)接口。
作為參考,一個(gè)簡(jiǎn)單的使用序列為:
ptr =MemAlloc(pool); /* use memory via ptr */ MemFree(pool, ptr);
在啟動(dòng)過程中調(diào)用:
pool= Create(mem, size, num);
2沒有可用內(nèi)存
如果沒有足夠的內(nèi)存滿足當(dāng)前分配請(qǐng)求,內(nèi)存分配函數(shù)會(huì)反饋相應(yīng)信息(如NULL指針)。用戶應(yīng)該檢查函數(shù)返回值并采取適當(dāng)?shù)拇胧?/p>
ptr =MemAlloc(pool); if(ptr ==NULL) { MemErrOutOfMemory(pool); } /* use memory via ptr */ MemFree(pool, ptr);
使用實(shí)時(shí)內(nèi)核時(shí),我們可以通過擴(kuò)展內(nèi)存分配函數(shù),進(jìn)一步避免丟失檢查和失敗處理的風(fēng)險(xiǎn),使用阻塞等待空閑內(nèi)存:
ptr =MemAllocWait(pool); /* use memory via ptr */ MemFree(pool, ptr); ptr =MemAllocWait(pool);
通過阻塞等待方式確保返回的指針是一個(gè)有效的內(nèi)存塊。強(qiáng)制性安全任務(wù)監(jiān)視器將檢測(cè)任務(wù)是否在定義的截止時(shí)間內(nèi)獲得足夠的內(nèi)存。
3內(nèi)存釋放到錯(cuò)誤內(nèi)存池
如果用戶負(fù)責(zé)將內(nèi)存釋放到正確的內(nèi)存池中(例如,內(nèi)存池是釋放內(nèi)存的參數(shù)),可能會(huì)出錯(cuò)。我們可以通過向info區(qū)域添加額外的參數(shù)來避免這個(gè)錯(cuò)誤。為了簡(jiǎn)單(快速)地訪問這些數(shù)據(jù),info區(qū)作為已分配內(nèi)存的一部分。應(yīng)用程序不能使用這部分?jǐn)?shù)據(jù),并且位于應(yīng)用程序內(nèi)存塊引用的前面:
改進(jìn)后的內(nèi)存使用順序如下:
ptr =MemAllocWait(pool); /* use memory via ptr */ MemFree(ptr);
4空閑內(nèi)存丟失
所謂的“內(nèi)存泄漏”發(fā)生在內(nèi)存分配且被使用之后,但沒有釋放內(nèi)存塊的時(shí)候。此錯(cuò)誤不容易檢測(cè),特別是當(dāng)分配和釋放操作將在不同的函數(shù)(或任務(wù))中實(shí)現(xiàn)時(shí)。
在不知道應(yīng)用程序細(xì)節(jié)的情況下,檢測(cè)內(nèi)存泄漏的一種方法是使用內(nèi)存看門狗,看門狗的工作方式類似于通常使用的執(zhí)行看門狗。
假設(shè)在內(nèi)存分配過程中定義了一個(gè)看門狗時(shí)間,這迫使我們?cè)谶@段時(shí)間內(nèi)觸發(fā)看門狗,以保持內(nèi)存塊有效。
我們將內(nèi)存計(jì)時(shí)數(shù)據(jù)存儲(chǔ)在info區(qū)域中。
為了檢查所有分配的內(nèi)存塊的看門狗時(shí)間周期,我們引入了一個(gè)檢查函數(shù)。下列偽代碼可以幫助了解我們?nèi)绾螜z查內(nèi)存塊。
voidMemCheck(pool) { foreach'block'in'pool'do: if('block::timeout'isgreater than0) then: decrement'block::timeout'by1 if('block::timeout'isequal to0) then: callMemErrTimeout(block) }
我們系統(tǒng)安全自檢過程中定期調(diào)用這個(gè)函數(shù)。使用序列如下所示。
ptr =MemAllocWait(timeout, pool); MemUseTrigger(ptr); /*use memory via ptr*/ MemFree(ptr);
如果錯(cuò)過了看門狗時(shí)間周期,我們可以在回調(diào)函數(shù)中執(zhí)行適當(dāng)?shù)膭?dòng)作:
voidMemErrTimeout(ptr) { /* action on timeout: */ /* log diagnostic data */ /* initiate safe state */ }
5內(nèi)存多次釋放
當(dāng)在沒有檢測(cè)機(jī)制的情況下多次(錯(cuò)誤地)釋放一個(gè)內(nèi)存塊時(shí),可能導(dǎo)致正在運(yùn)行系統(tǒng)的奇怪行為。這種錯(cuò)誤很難調(diào)試,必須避免。
在info區(qū)域中添加一個(gè)額外的冗余值,可以非常有效地處理這個(gè)問題。推薦使用內(nèi)存池參數(shù)的補(bǔ)值,需在內(nèi)存分配函數(shù)中將這兩個(gè)值設(shè)置為匹配的一對(duì)。
內(nèi)存釋放函數(shù)可以檢查這些冗余信息,將內(nèi)存塊放回相應(yīng)的內(nèi)存池中,然后破壞冗余信息。實(shí)現(xiàn)偽代碼如下:
voidMemFree(ptr) { if('ptr::pool'isequal to complement of'ptr::inv_pool') then: release memory block'ptr'to'ptr::pool' set'ptr::inv_pool'to'ptr::pool' else: callMemErrDoubleFree(ptr) }
最后,我們可以在回調(diào)函數(shù)中為這種錯(cuò)誤情況定義適當(dāng)?shù)牟僮鳎篗emErrDoubleFree(ptr)。
6釋放后繼續(xù)使用內(nèi)存
這個(gè)編程錯(cuò)誤聽起來不可思議,但在多任務(wù)環(huán)境中,這個(gè)錯(cuò)誤可能存在,在最壞的情況下,很長一段時(shí)間都沒有被發(fā)現(xiàn)。
為了檢測(cè)這種情況,我們可以重用info區(qū)域中的數(shù)據(jù)冗余。在這種情況下,我們?cè)谑褂脙?nèi)存塊之前檢查冗余是否損壞。為了使代碼順序盡可能簡(jiǎn)單,我們可以集成內(nèi)存看門狗觸發(fā):
voidMemStartAccess(ptr) { if('ptr::pool'is not equal to complement of'ptr::inv_pool') then: callMemErrUsedFree(ptr) else set'ptr::timeout'to'ptr::watchdog_time' }
最后,在回調(diào)函數(shù)MemErrUsedFree(ptr)中為這種錯(cuò)誤情況定義適當(dāng)?shù)牟僮鳌?/p>
在使用內(nèi)存塊之前,該檢測(cè)機(jī)制將需要一個(gè)額外的函數(shù)調(diào)用。
ptr =MemAllocWait(timeout, pool); MemStartAccess(ptr); /* use memory block via ptr */ MemFree(ptr);
7使用時(shí)釋放內(nèi)存
這個(gè)編程錯(cuò)誤與前面的錯(cuò)誤屬于同一類。在多任務(wù)環(huán)境中,可能釋放了被中斷任務(wù)占用的內(nèi)存塊。該任務(wù)重新運(yùn)行時(shí),其使用的內(nèi)存已經(jīng)被釋放。
針對(duì)這個(gè)問題,我們可以使用一個(gè)對(duì)稱函數(shù)的解決方案。對(duì)應(yīng)MemStartAccess()函數(shù),引入結(jié)束函數(shù)。這個(gè)新函數(shù)可以通知用戶內(nèi)存塊不能使用了:
void MemEndAccess (ptr);
通過相應(yīng)的阻塞函數(shù)來釋放內(nèi)存,我們可以避免這類編程錯(cuò)誤。
void MemFreeWait (ptr);
對(duì)應(yīng)的動(dòng)態(tài)內(nèi)存使用序列如下:
ptr =MemAllocWait(timeout, pool); MemStartAccess(ptr); /*use memory block via ptr*/ MemEndAccess(ptr); MemFreeWait(ptr);
總結(jié)
在本文中,我們發(fā)現(xiàn)了一種在IEC61508系統(tǒng)中使用動(dòng)態(tài)內(nèi)存的方法,避免相應(yīng)的編程錯(cuò)誤并在檢測(cè)到錯(cuò)誤后做出響應(yīng)。我們?yōu)檫@些安全功能付出了相應(yīng)的代價(jià):每個(gè)分配的內(nèi)存塊將占用額外內(nèi)存空間,消耗了CPU運(yùn)行時(shí)間。
盡管如此,還是建議在安全關(guān)鍵型系統(tǒng)中謹(jǐn)慎使用動(dòng)態(tài)內(nèi)存。
Flexible Safety RTOS是基于μC/OS-II+MPU機(jī)制實(shí)現(xiàn)的功能安全操作系統(tǒng),提供了基于塊的內(nèi)存管理機(jī)制。麥
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4372瀏覽量
64344 -
動(dòng)態(tài)內(nèi)存
+關(guān)注
關(guān)注
1文章
25瀏覽量
8089 -
靜態(tài)內(nèi)存
+關(guān)注
關(guān)注
0文章
6瀏覽量
1453
原文標(biāo)題:IEC61508系統(tǒng)中的動(dòng)態(tài)內(nèi)存使用
文章出處:【微信號(hào):麥克泰技術(shù),微信公眾號(hào):麥克泰技術(shù)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
動(dòng)態(tài)內(nèi)存管理模塊的設(shè)計(jì)原理與實(shí)現(xiàn)

C語言知識(shí)總結(jié):動(dòng)態(tài)內(nèi)存分配
C語言程序設(shè)計(jì)中動(dòng)態(tài)內(nèi)存分配如何實(shí)現(xiàn)
瑞薩電子功能安全IEC61508解決方案介紹(2)

請(qǐng)問使用動(dòng)態(tài)內(nèi)存分配安全嗎?
使用動(dòng)態(tài)內(nèi)存分配安全嗎
動(dòng)態(tài)內(nèi)存分配是什么意思
動(dòng)態(tài)內(nèi)存錯(cuò)誤的靜態(tài)檢測(cè)

動(dòng)態(tài)內(nèi)存管理在面向嵌入式實(shí)時(shí)系統(tǒng)中的研究
基于IEC61508開發(fā)功能安全的處理器詳細(xì)介紹

嵌入式中需要用到動(dòng)態(tài)內(nèi)存嗎
嵌入式C語言中的動(dòng)態(tài)內(nèi)存管理和動(dòng)態(tài)內(nèi)存分配
Xilinx為IEC61508和ISO26262認(rèn)證的安全應(yīng)用降低風(fēng)險(xiǎn)并提高效率

瑞薩基于IEC61508的功能安全解決方案介紹(1)

評(píng)論