簡體   English   中英

為什么我們不應該在嵌入式系統中動態分配不同大小的內存

[英]Why shouldn't we have dynamic allocated memory with different size in embedded system

我聽說在嵌入式系統中,我們應該使用一些預先分配的固定大小的內存塊(比如伙伴內存系統?)。 誰能給我一個詳細的解釋為什么? 謝謝,

在嵌入式系統中,您的內存非常有限。 因此,如果您偶爾只丟失一個字節的內存(因為您分配了它,但沒有釋放它),這將很快耗盡系統內存(1 GB 的 RAM,泄漏率為 1/小時)時間。如果您有 4kB RAM,則不會那么長)

本質上,避免動態內存的行為是為了避免程序中錯誤的影響。 由於靜態內存分配是完全確定性的(而動態內存分配不是),因此僅使用靜態內存分配就可以抵消此類錯誤。 一個重要因素是嵌入式系統通常用於安全關鍵應用程序。 幾個小時的停機時間可能會造成數百萬美元的損失,或者可能發生事故。

此外,取決於動態內存分配器,不確定性也可能需要不確定的時間,這可能會導致更多的錯誤,尤其是在依賴嚴格計時的系統中(感謝Clifford提到這一點)。 這種類型的錯誤通常很難測試和重現,因為它依賴於非常具體的執行路徑。

此外,嵌入式系統通常沒有 MMU,因此沒有像內存保護這樣的東西。 如果內存不足並且處理該條件的代碼不起作用,則最終可能會將任何內存作為指令執行(可能會發生壞事!但是這種情況僅與動態內存分配間接相關)。

正如沉浩所說,碎片化也是一種危險。 它是否可能發生取決於您的具體用例,但在嵌入式系統中,由於碎片,很容易丟失 50% 的 RAM。 如果分配始終具有完全相同大小的塊,則只能避免碎片。

性能也很重要(取決於用例 - 感謝Hao Shen )。 靜態分配的內存由編譯器分配,而malloc()和類似的需要在設備上運行,因此消耗 CPU 時間(和功率)。

許多嵌入式操作系統(例如 ChibiOS)支持某種動態內存分配器。 但是使用它只會增加發生意外問題的可能性。

請注意,這些參數通常可以通過使用較小的靜態分配內存池來規避。 這不是一個真正的解決方案,因為這些池中的內存仍然可能耗盡,但這只會影響系統的一小部分。

正如Stephano Sanfilippo所指出的,有些系統甚至沒有足夠的資源來支持動態內存分配。

注意:大多數編碼標准,包括JPL 編碼標准DO-178B (用於關鍵航空電子代碼 - 感謝Stephano Sanfilippo )禁止使用 malloc。

我還假設MISRA C 標准因為這個論壇帖子而禁止malloc() - 但是我無權訪問標准本身。

這里不使用動態堆內存分配的主要原因基本上是:

a) 確定性和相關性,b) 記憶碎片。

在那些小型嵌入式應用程序中,內存泄漏通常不是問題,因為它們會在開發/測試的早期被檢測到。

然而,內存碎片可能變得不確定,導致(最佳情況)在現場應用程序中的隨機時間和點出現內存不足錯誤。

在使用動態分配的開發過程中預測應用程序的實際最大內存使用量也可能非常重要,而靜態分配的內存量在編譯時是已知的,並且檢查該內存是否可以由硬件與否。

從固定大小的塊池中分配內存比動態內存分配有幾個優點。 它可以防止堆碎片,並且更具確定性。

通過動態內存分配,動態大小的內存塊是從固定大小的堆中分配的。 分配不一定按照分配的順序釋放。 隨着時間的推移,這可能導致堆的空閑部分在堆的分配部分之間划分的情況。 隨着這種碎片的發生,滿足更大內存分配的請求會變得更加困難。 如果請求大內存分配,並且堆中沒有足夠大的連續空閑部分,則分配將失敗。 堆可能有足夠的總可用內存,但如果它全部碎片化並且沒有連續的部分,則分配將失敗。 由於堆碎片而導致 malloc() 失敗的可能性在嵌入式系統中是不可取的。

消除碎片的一種方法是在釋放時將較小的內存分配重新加入較大的連續部分。 這可以通過多種方式完成,但它們都需要時間,並且會使系統的確定性降低。 例如,如果內存管理器在釋放內存分配時掃描堆,則 free() 完成所需的時間可能會根據與正在釋放的分配相鄰的內存類型而有所不同。 這在許多嵌入式系統中是不確定的和不可取的。

從固定大小的塊池中分配不會導致碎片。 只要有一些空閑塊,分配就不會失敗,因為每個塊的大小都是正確的。 此外,從固定大小的塊池中分配和釋放更簡單。 所以分配和釋放函數可以寫成確定性的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM