0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式中是否使用動(dòng)態(tài)內(nèi)存?

黃工的嵌入式技術(shù)圈 ? 來(lái)源:黃工的嵌入式技術(shù)圈 ? 作者:黃工的嵌入式技術(shù) ? 2020-02-28 17:03 ? 次閱讀

所謂動(dòng)態(tài)內(nèi)存分配(Dynamic Memory Allocation)就是指在程序執(zhí)行的過(guò)程中動(dòng)態(tài)地分配或者回收存儲(chǔ)空間的分配內(nèi)存的方法。

動(dòng)態(tài)內(nèi)存分配不像數(shù)組等靜態(tài)內(nèi)存分配方法那樣需要預(yù)先分配存儲(chǔ)空間,而是由系統(tǒng)根據(jù)程序的需要即時(shí)分配,且分配的大小就是程序要求的大小。

關(guān)于靜態(tài)內(nèi)存與動(dòng)態(tài)內(nèi)存

1.1、靜態(tài)和動(dòng)態(tài)內(nèi)存的特點(diǎn)
在探討這個(gè)問(wèn)題之前我們先來(lái)對(duì)比下靜態(tài)內(nèi)存和動(dòng)態(tài)內(nèi)存的特點(diǎn):
1. 創(chuàng)建的時(shí)間不同:創(chuàng)建的時(shí)間不同:靜態(tài)分配發(fā)生在程序編譯和連接的時(shí)候。動(dòng)態(tài)分配則發(fā)生在程序調(diào)入和執(zhí)行的時(shí)候。

編譯鏈接過(guò)程中已經(jīng)分配好的

代碼運(yùn)行過(guò)程中使用rt_malloc分配:

1staticvoidonmessage_text(rws_socketsocket,constchar*text,constunsignedintlen) 2{ 3char*buff=RT_NULL; 4 5buff=(char*)rt_malloc(2048); 6 7rt_memset(buff,0x00,2048); 8rt_memcpy(buff,text,len); 9 10LOG_D("message(txt),%d(byte):%s",len,buff); 11 12if(buff!=RT_NULL) 13{ 14rt_free(buff); 15} 16}

2. 創(chuàng)建的空間不同:堆都是動(dòng)態(tài)分配的,沒(méi)有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動(dòng)態(tài)分配。靜態(tài)分配是編譯器完成的,比如局部變量的分配。動(dòng)態(tài)分配由函數(shù)malloc進(jìn)行分配。不過(guò)棧的動(dòng)態(tài)分配和堆不同,他的動(dòng)態(tài)分配是由編譯器進(jìn)行釋放,無(wú)需我們手工實(shí)現(xiàn)。

1.2、靜態(tài)和動(dòng)態(tài)內(nèi)存的優(yōu)缺點(diǎn)

在了解了靜態(tài)內(nèi)存和動(dòng)態(tài)內(nèi)存不同的特點(diǎn)后可以分析出它們?cè)诓煌姆矫婢哂胁煌膬?yōu)缺點(diǎn):
1.靜態(tài)內(nèi)存編譯階段就分配好了,不會(huì)存在分配失敗的情況,除非系統(tǒng)內(nèi)存被分配完了,但是在編譯階段就可以查出。動(dòng)態(tài)內(nèi)存在運(yùn)行中分配,在正常運(yùn)行的情況下可能夠正常分配,在某種環(huán)境下可能分配失敗 ,這樣就對(duì)開(kāi)發(fā)者的代碼水平要求更高,要求開(kāi)發(fā)者需要對(duì)代碼的健壯性有要求。

2.靜態(tài)內(nèi)存由于是編譯階段分配好的,而動(dòng)態(tài)內(nèi)存是由運(yùn)行中分配,這樣動(dòng)態(tài)內(nèi)存可以被高效復(fù)用,當(dāng)某段程序使用完畢后,可以將內(nèi)存交換給內(nèi)存池中等待下次程序的分配,由于這種機(jī)制,開(kāi)發(fā)者可以利用更小的內(nèi)存開(kāi)發(fā)更大型的程序。

3. 動(dòng)態(tài)內(nèi)存由于是動(dòng)態(tài)分配,所以涉及到分配和釋放的問(wèn)題,假設(shè)X程序在分配了ABC3塊內(nèi)存,程序執(zhí)行完畢后AC區(qū)域內(nèi)存被釋放,但是由于開(kāi)發(fā)者的疏忽導(dǎo)致B區(qū)域的內(nèi)存被遺留。而X程序又是會(huì)被反復(fù)調(diào)用的,這樣我們的內(nèi)存區(qū)域由于有沒(méi)有釋放的區(qū)域?qū)е旅看握{(diào)用就會(huì)占用一段區(qū)域,最終系統(tǒng)就沒(méi)有內(nèi)存可以使用。這種情況一般在產(chǎn)品實(shí)際體現(xiàn)為最開(kāi)始的時(shí)候設(shè)備正常工作,但是運(yùn)行了幾個(gè)小時(shí)或者幾天后死機(jī)。這種情況一般被稱作內(nèi)存泄漏(Memory Leak)。


4. 在嵌入式RTOS中線程函數(shù)中使用靜態(tài)內(nèi)存,也就是在線程中定義局部變量,會(huì)加大線程??臻g的開(kāi)銷。

裸機(jī)開(kāi)發(fā)和RTOS開(kāi)發(fā)的特點(diǎn)

1. 代碼規(guī)模:裸機(jī)開(kāi)發(fā)的項(xiàng)目一般代碼規(guī)模都比較小,對(duì)于一般開(kāi)發(fā)者都難于駕馭使用裸機(jī)開(kāi)發(fā)超大規(guī)模項(xiàng)目,人力成本和時(shí)間成本都太高。反而由于RTOS的模塊化特性,更容易開(kāi)發(fā)出代碼規(guī)模大的項(xiàng)目。


2. 系統(tǒng)穩(wěn)定性:在機(jī)電,航空,汽車等行業(yè)都是需要高實(shí)時(shí)性、高穩(wěn)定性和高安全性的。對(duì)于RTOS來(lái)說(shuō),系統(tǒng)任務(wù)的劃分調(diào)度都是系統(tǒng)管理,當(dāng)開(kāi)發(fā)者對(duì)其機(jī)制了解不清楚的情況下反而帶來(lái)了部分風(fēng)險(xiǎn)。

除此之外RTOS上的內(nèi)存管理也是很大影響系統(tǒng)的,對(duì)于RTOS上一般不會(huì)存在MMU內(nèi)存管理單元,也就代表大部分運(yùn)行RTOS的芯片上都沒(méi)有虛擬地址映射,那么就無(wú)法利用物理地址和虛擬地址的特性進(jìn)行內(nèi)存整理,避免內(nèi)存泄漏。所以說(shuō)在RTOS動(dòng)態(tài)內(nèi)存這塊內(nèi)存有風(fēng)險(xiǎn)。

嵌入式中是否應(yīng)該使用動(dòng)態(tài)內(nèi)存

明白不同內(nèi)存的優(yōu)缺點(diǎn)和裸機(jī)RTOS的特點(diǎn)之后,我們?cè)诨仡^來(lái)分析 “嵌入式中是否應(yīng)該使用動(dòng)態(tài)內(nèi)存?”

在實(shí)時(shí)嵌入式系統(tǒng)中,由于系統(tǒng)軟件并不像PC上復(fù)雜,一般都是很簡(jiǎn)單的內(nèi)存使用,所以一般也不使用動(dòng)態(tài)內(nèi)存管理,但是隨著RTOS面臨的任務(wù)越來(lái)越重,尤其是IoTAIoT的到來(lái),讓許多消費(fèi)級(jí)產(chǎn)品運(yùn)行的RTOS的負(fù)擔(dān)越來(lái)越重。

在這種情況下繼續(xù)使用靜態(tài)內(nèi)存開(kāi)發(fā)會(huì)極大的限制開(kāi)發(fā)進(jìn)度,整個(gè)開(kāi)發(fā)的靈活性非常低。同時(shí)靜態(tài)的內(nèi)存無(wú)法復(fù)用使用同一片內(nèi)存區(qū)域,相比與動(dòng)態(tài)內(nèi)存在大型項(xiàng)目中一般會(huì)使用更多的內(nèi)存,在內(nèi)存大小不容樂(lè)觀的嵌入式系統(tǒng)是很難接受的。

但是針對(duì)一些高穩(wěn)定性和高安全性的項(xiàng)目來(lái)說(shuō),使用動(dòng)態(tài)內(nèi)存就需要好好斟酌下,由于RTOS上基本沒(méi)有MMU的硬件支持或者是系統(tǒng)軟件支持,所以不可避免的系統(tǒng)中會(huì)出現(xiàn)內(nèi)存碎片,從而有可能導(dǎo)致系統(tǒng)異常。最終說(shuō)了這么多總結(jié)成以下幾點(diǎn):
1. 沒(méi)有使用RTOS的項(xiàng)目:不建議使用動(dòng)態(tài)內(nèi)存,這種項(xiàng)目一般很簡(jiǎn)單,不必使用動(dòng)態(tài)內(nèi)存增大系統(tǒng)開(kāi)銷和復(fù)雜度。


2. 使用RTOS的消費(fèi)級(jí)項(xiàng)目:建議使用動(dòng)態(tài)內(nèi)存,一般這種項(xiàng)目代碼復(fù)雜度比裸機(jī)高,合理使用動(dòng)態(tài)內(nèi)存會(huì)有效降低內(nèi)存的開(kāi)銷。同時(shí)很多Github項(xiàng)目的linux程序都是會(huì)使用內(nèi)存管理,有這套機(jī)制能更加方便的移植代碼。


3. 使用RTOS的軍工、航天、醫(yī)療等高穩(wěn)定性和高安全性項(xiàng)目:建議盡量降低對(duì)動(dòng)態(tài)內(nèi)存的使用與依賴以確保系統(tǒng)的穩(wěn)定性。當(dāng)然也不代表動(dòng)態(tài)內(nèi)存就無(wú)法在這些項(xiàng)目上使用,只是要求系統(tǒng)開(kāi)發(fā)者對(duì)系統(tǒng)內(nèi)存的把控要求更高。

RT-Thread的內(nèi)存管理

RT-Thread 操作系統(tǒng)在內(nèi)存管理上,根據(jù)上層應(yīng)用及系統(tǒng)資源的不同,有針對(duì)性地提供了不同的內(nèi)存分配管理算法。總體上可分為兩類:內(nèi)存堆管理與內(nèi)存池管理,而內(nèi)存堆管理又根據(jù)具體內(nèi)存設(shè)備劃分為三種情況:

第一種是針對(duì)小內(nèi)存塊的分配管理(小內(nèi)存管理算法);
第二種是針對(duì)大內(nèi)存塊的分配管理(slab 管理算法);
第三種是針對(duì)多內(nèi)存堆的分配情況(memheap 管理算法)。

小內(nèi)存管理算法是一個(gè)簡(jiǎn)單的內(nèi)存分配算法。初始時(shí),它是一塊大的內(nèi)存。當(dāng)需要分配內(nèi)存塊時(shí),將從這個(gè)大的內(nèi)存塊上分割出相匹配的內(nèi)存塊,然后把分割出來(lái)的空閑內(nèi)存塊還回給堆管理系統(tǒng)中。每個(gè)內(nèi)存塊都包含一個(gè)管理用的數(shù)據(jù)頭,通過(guò)這個(gè)頭把使用塊與空閑塊用雙向鏈表的方式鏈接起來(lái)。


RT-Thread 的 slab 分配器是在 DragonFly BSD 創(chuàng)始人 Matthew Dillon 實(shí)現(xiàn)的 slab 分配器基礎(chǔ)上,針對(duì)嵌入式系統(tǒng)優(yōu)化的內(nèi)存分配算法。最原始的 slab 算法是 Jeff Bonwick 為 Solaris 操作系統(tǒng)而引入的一種高效內(nèi)核內(nèi)存分配算法。

memheap 管理算法適用于系統(tǒng)含有多個(gè)地址可不連續(xù)的內(nèi)存堆。使用 memheap 內(nèi)存管理可以簡(jiǎn)化系統(tǒng)存在多個(gè)內(nèi)存堆時(shí)的使用:當(dāng)系統(tǒng)中存在多個(gè)內(nèi)存堆的時(shí)候,用戶只需要在系統(tǒng)初始化時(shí)將多個(gè)所需的 memheap 初始化,并開(kāi)啟 memheap 功能就可以很方便地把多個(gè) memheap(地址可不連續(xù))粘合起來(lái)用于系統(tǒng)的 heap 分配。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式常用數(shù)據(jù)結(jié)構(gòu)有哪些

    嵌入式編程,數(shù)據(jù)結(jié)構(gòu)的選擇和使用對(duì)于程序的性能、內(nèi)存管理以及開(kāi)發(fā)效率都具有重要影響。嵌入式系統(tǒng)由于資源受限(如處理器速度、內(nèi)存大小等),
    的頭像 發(fā)表于 09-02 15:25 ?217次閱讀

    嵌入式系統(tǒng)的實(shí)時(shí)操作系統(tǒng)

    嵌入式RTOS是嵌入式應(yīng)用程序運(yùn)行、相互交互和與外界通信的底層軟件機(jī)制。在本節(jié),您將了解嵌入式軟件開(kāi)發(fā)人員使用哪些流行RTOS以及它們運(yùn)行的嵌入式
    的頭像 發(fā)表于 08-20 11:28 ?276次閱讀

    提升嵌入式系統(tǒng)可靠性的有效策略

    對(duì)嵌入式工程師來(lái)說(shuō)一個(gè)很大的好處是,我們的IDE和工具鏈可以自動(dòng)產(chǎn)生應(yīng)用程序或內(nèi)存空間校驗(yàn)和(Checksum),從而根據(jù)這個(gè)校驗(yàn)和驗(yàn)證應(yīng)用程序是否完好。有
    發(fā)表于 04-26 14:50 ?292次閱讀
    提升<b class='flag-5'>嵌入式</b>系統(tǒng)可靠性的有效策略

    你知道嗎? 51單片機(jī)也有動(dòng)態(tài)內(nèi)存分配

    一、簡(jiǎn)述其實(shí)在51單片機(jī)也可以使用動(dòng)態(tài)內(nèi)存,動(dòng)態(tài)內(nèi)存其實(shí)就是劃出一塊內(nèi)存區(qū)域,將這塊內(nèi)存進(jìn)行管理,稱為
    的頭像 發(fā)表于 04-26 08:10 ?1022次閱讀
    你知道嗎? 51單片機(jī)也有<b class='flag-5'>動(dòng)態(tài)內(nèi)存</b>分配

    嵌入式fpga是什么意思

    嵌入式FPGA是指將FPGA技術(shù)集成到嵌入式系統(tǒng)的一種解決方案。嵌入式系統(tǒng)是一種為特定應(yīng)用而設(shè)計(jì)的計(jì)算機(jī)系統(tǒng),它通常包括處理器、內(nèi)存、外設(shè)
    的頭像 發(fā)表于 03-15 14:29 ?1011次閱讀

    C語(yǔ)言中的動(dòng)態(tài)內(nèi)存管理講解

    本章將講解 C 動(dòng)態(tài)內(nèi)存管理。C 語(yǔ)言為內(nèi)存的分配和管理提供了幾個(gè)函數(shù)。這些函數(shù)可以在 頭文件中找到。
    的頭像 發(fā)表于 02-23 14:03 ?310次閱讀
    C語(yǔ)言中的<b class='flag-5'>動(dòng)態(tài)內(nèi)存</b>管理講解

    嵌入式學(xué)習(xí)步驟

    語(yǔ)言編寫(xiě)。但是,有些嵌入式系統(tǒng)也使用其他編程語(yǔ)言,例如Python或Java。 (3).了解硬件:深入了解您要控制的硬件設(shè)備的功能和特性。您需要了解嵌入式系統(tǒng)的處理器、內(nèi)存、I/O端口、傳感器和其他
    發(fā)表于 02-02 15:24

    嵌入式系統(tǒng)堆棧監(jiān)控的作用

    在微控制器或微處理器,堆棧是內(nèi)存的一個(gè)保留區(qū)域,用于存儲(chǔ)臨時(shí)數(shù)據(jù)和函數(shù)調(diào)用信息,管理函數(shù)的執(zhí)行,跟蹤返回地址、局部變量和函數(shù)參數(shù)。堆棧監(jiān)控是嵌入式系統(tǒng)運(yùn)行起關(guān)鍵作用的一項(xiàng)安全措施,
    的頭像 發(fā)表于 01-05 11:13 ?365次閱讀

    嵌入式C語(yǔ)言高手煉成之內(nèi)存操作篇

    嵌入式系統(tǒng)的編程,常常要求在特定的內(nèi)存單元讀寫(xiě)內(nèi)容,匯編有對(duì)應(yīng)的MOV指令,而除C/C++以外的其它編程語(yǔ)言基本沒(méi)有直接訪問(wèn)絕對(duì)地址的能力。在嵌入式系統(tǒng)的實(shí)際調(diào)試
    的頭像 發(fā)表于 12-11 17:20 ?415次閱讀

    嵌入式系統(tǒng),內(nèi)存不夠用了怎么辦?

    嵌入式系統(tǒng)內(nèi)存不夠用了怎么辦? 隨著技術(shù)的不斷發(fā)展,微型化、便攜化的智能化設(shè)備正逐漸成為人們生活不可或缺的一部分。然而,在這些設(shè)備,
    的頭像 發(fā)表于 10-29 16:33 ?854次閱讀

    基于嵌入式WEB的電站數(shù)據(jù)動(dòng)態(tài)監(jiān)控軟件設(shè)計(jì)

    電子發(fā)燒友網(wǎng)站提供《基于嵌入式WEB的電站數(shù)據(jù)動(dòng)態(tài)監(jiān)控軟件設(shè)計(jì).pdf》資料免費(fèi)下載
    發(fā)表于 10-24 10:01 ?0次下載
    基于<b class='flag-5'>嵌入式</b>WEB的電站數(shù)據(jù)<b class='flag-5'>動(dòng)態(tài)</b>監(jiān)控軟件設(shè)計(jì)

    DMA開(kāi)辟緩存怎么使用動(dòng)態(tài)內(nèi)存

    開(kāi)辟20kb左右的緩存空間,如果直接用全局變量數(shù)組,在不需要用到DMA時(shí),那這20k的內(nèi)存就一直不能釋放,好浪費(fèi)。若使用malloc來(lái)開(kāi)辟動(dòng)態(tài)內(nèi)存,應(yīng)該是放在堆區(qū)吧?堆區(qū)不是默認(rèn)只有512字節(jié)?還要修改啟動(dòng)文件的堆大???
    發(fā)表于 10-23 06:53

    嵌入式系統(tǒng)動(dòng)態(tài)內(nèi)存的使用技巧

    一種比較好的方法是建立日志塊,即每次分配內(nèi)存時(shí)記錄該內(nèi)存塊的指針和大小,釋放時(shí)再去除該日志塊,如果有內(nèi)存泄露就會(huì)有對(duì)應(yīng)的日志塊記錄這些內(nèi)存沒(méi)有釋放,這樣就可以提醒程序員進(jìn)行查錯(cuò)。
    發(fā)表于 10-12 15:22 ?262次閱讀

    C語(yǔ)言程序設(shè)計(jì)動(dòng)態(tài)內(nèi)存分配如何實(shí)現(xiàn)

    C語(yǔ)言程序設(shè)計(jì),動(dòng)態(tài)內(nèi)存分配如何實(shí)現(xiàn),需要注意哪些問(wèn)題?
    發(fā)表于 09-28 16:53 ?1136次閱讀

    嵌入式系統(tǒng)內(nèi)存碎片產(chǎn)生過(guò)程說(shuō)明

    嵌入式系統(tǒng),內(nèi)存是十分有限而且是十分珍貴的,用一塊內(nèi)存就少了一塊內(nèi)存,而在分配隨著
    發(fā)表于 09-21 12:22 ?501次閱讀
    <b class='flag-5'>嵌入式</b>系統(tǒng)<b class='flag-5'>中</b><b class='flag-5'>內(nèi)存</b>碎片產(chǎn)生過(guò)程說(shuō)明