彈性內(nèi)存分配在IOT中的重要性
一般而言,開發(fā)人員不太會考慮內(nèi)存分配。畢竟,現(xiàn)代計算機、平板電腦和服務(wù)器的內(nèi)存如此之大,通??雌饋硐袷菬o限的資源。而且,內(nèi)存分配失敗或錯誤不太可能發(fā)生,即使出現(xiàn)問題,系統(tǒng)通常默認退出程序。
然而,當涉及到物聯(lián)網(wǎng)(IoT)時,情況大有不同。在這些嵌入式連接設(shè)備中,內(nèi)存會變得更加搶手,多個程序會爭奪有限的資源;而且集成系統(tǒng)越小,內(nèi)存也更小。因此,最好將其視為有限的資源并保守使用。
正是在這種背景下,內(nèi)存分配(malloc)在IOT行業(yè)中非常重要。malloc是計算機在運行程序或進程時動態(tài)分配內(nèi)存的過程。尤其是對于連接到互聯(lián)網(wǎng)的設(shè)備,正確處理malloc直接決定其性能好壞。
下面,讓我們來看看開發(fā)人員如何在他們的內(nèi)存分配方法中彈性設(shè)計,以及這對未來的物聯(lián)網(wǎng)設(shè)備意味著什么。
1、內(nèi)存分配和物聯(lián)網(wǎng)設(shè)備
傳統(tǒng)上,內(nèi)存分配(malloc)經(jīng)常不用于嵌入式系統(tǒng)。這是因為較舊的設(shè)備通常不會連接到互聯(lián)網(wǎng),因此計算的內(nèi)存需求并不大。
但是,這些較舊的設(shè)備在系統(tǒng)啟動時創(chuàng)建了一個資源池來分配資源。一個資源可以是一個連接,一個系統(tǒng)可以配置n個來自靜態(tài)分配池的連接。
在未連接Internet的系統(tǒng)中,系統(tǒng)的狀態(tài)通常受到一定程度的限制,因此更容易估計內(nèi)存分配malloc的上限。但是,一旦嵌入式系統(tǒng)連接到互聯(lián)網(wǎng),這種情況就會發(fā)生巨大變化。
例如,一個設(shè)備需要計算多個連接,并且每個連接都有不同的內(nèi)存需求,這取決于連接的用途。每個連接上的數(shù)據(jù)流所需的緩沖內(nèi)存取決于連接的延遲,通過使用某些概率函數(shù)或其他網(wǎng)絡(luò)連接的行為方式來處理數(shù)據(jù)包丟失,從而獲得一定的吞吐量。
通常這在現(xiàn)代高端系統(tǒng)上不是問題。但是,開發(fā)人員在嵌入式環(huán)境中面臨有限的內(nèi)存資源,我們不能簡單地假設(shè)有足夠的內(nèi)存。
這就是為什么在物聯(lián)網(wǎng)嵌入式開發(fā)中,考慮如何規(guī)避內(nèi)存分配錯誤或者malloc失敗是非常重要的。
2、現(xiàn)代嵌入式系統(tǒng)和malloc
在現(xiàn)代的嵌入式系統(tǒng)中,malloc的使用頻率更高,許多嵌入式系統(tǒng)和平臺都有不錯的malloc實現(xiàn)。這種轉(zhuǎn)變的原因是現(xiàn)代連接的嵌入式系統(tǒng)執(zhí)行更多的任務(wù),通常無法靜態(tài)地為所有程序的執(zhí)行分配所需的最大資源。
在現(xiàn)代互聯(lián)嵌入式系統(tǒng)中積極使用malloc,這種轉(zhuǎn)變需要更徹底和系統(tǒng)的軟件測試來發(fā)現(xiàn)錯誤。
通常,malloc錯誤不會系統(tǒng)測試,因為它發(fā)生的概率極低,不值得這么去做。正因為malloc錯誤非常罕見,所以其漏洞在發(fā)現(xiàn)之前可能已存在數(shù)年。
3、mallocfail工具:如何測試錯誤
令人高興的是,開發(fā)人員可以利用軟件來測試分配錯誤。有一種新穎的方法是通過運行一個程序,在發(fā)生分配的所有執(zhí)行路徑中注入分配錯誤。這可以通過mallocfail工具實現(xiàn)。
顧名思義,Mallocfail以確定的方式測試malloc錯誤。該工具不是隨機測試,而是通過不同的控制路徑自動枚舉malloc錯誤。它的靈感來自于Stack Overflow。
簡而言之,此工具使用自定義版本分配器malloc、calloc和realloc。每次運行自定義分配器時,都會使用libbacktrace獲取當前線程的函數(shù)調(diào)用堆棧,生成對應的 sha256 哈希值。然后,該工具檢查是否出現(xiàn)新的哈希值。如果出現(xiàn)從未見過的哈希(特定的調(diào)用堆棧),則內(nèi)存分配malloc失敗,并將哈希值存儲在內(nèi)存中寫入磁盤;如果之前見過,則正常調(diào)用分配器libc版本。每次程序啟動時,已見過的哈希值都會從磁盤加載。
這是我第一手使用過的東西,發(fā)現(xiàn)非常有用。例如,我們在嵌入式邊緣軟件開發(fā)工具包上成功測試了mallocfail。該工具成功識別了SDK及其第三方庫中的一些問題,而且它們的問題現(xiàn)已修復了。
4、處理malloc問題
在復雜的系統(tǒng)中,處理分配錯誤可能有點棘手。例如,處理一個事件需要考慮分配多少內(nèi)存。當然,解決方案有很多種。最重要的是分配必要的內(nèi)存,以便在分配失敗時可以將錯誤傳遞回程序,不至于某些問題被悄無聲息的隱藏其中。
處理malloc 失敗的能力是我們團隊經(jīng)??紤]的問題。當然,這在其他設(shè)備上可能并沒有什么,但它會在連接到互聯(lián)網(wǎng)的嵌入式設(shè)備上引起大問題。
因此,我們的 SDK 會計算限制某些資源的功能,包括連接、流、緩沖區(qū)等。這樣,系統(tǒng)配置限制使用的內(nèi)存量,以免發(fā)生malloc錯誤。
通常,系統(tǒng)內(nèi)存不足會導致系統(tǒng)難以運行。因此,通過限制同時發(fā)生的功能/任務(wù),降低內(nèi)存分配錯誤的概率是很有意義的。
回首過去,我已經(jīng)在這個互聯(lián)網(wǎng)設(shè)備領(lǐng)域工作了二十年,期待同行開發(fā)人員在現(xiàn)代嵌入式開發(fā)中,采用最佳的malloc實踐。
建議您深入考慮嵌入式設(shè)備如何解決內(nèi)存分配問題,積極研究使用內(nèi)存的最有效方式。盡可能使用動態(tài)內(nèi)存分配和mallocfail測試進行開發(fā),因為它對嵌入式物聯(lián)網(wǎng)設(shè)備的性能及其可用性至關(guān)重要。