那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何在單片機中使用malloc函數

jf_78858299 ? 來源:矜辰所致 ? 作者: 矜辰所致 ? 2023-04-24 09:50 ? 次閱讀
  • 前言
  • 一、malloc 函數簡介
  • 二、malloc 之于單片機
    • 2.1 malloc 函數申請的內存在哪里?
    • 2.2 用與不用malloc的區別
  • 三、malloc可能遇到的問題
    • 3.1 內存碎片
    • 3.2 內存管理
  • 四、結語(用還是不用?)

前言

最近更新 RT-Thread 專欄到了內存管理的時候,想了想該怎么來說明這個內存管理,實際上在平時使用STM32做一般產品的時候基本不會用到 malloc 函數,即便是使用了操作系統,在業務邏輯不復雜的情況下,還是用不上malloc。

但是每個嵌入式 RTOS 都會有自己的內存管理方式,本文就來聊聊我對 malloc 函數在單片機程序設計中的一些看法。

本文并不是要說明在單片機中怎么使用 malloc函數,而是根據博主自己的理解,從函數使用的根本上來分析需不需要使用,何時何地使用。

本文的探討是單片機領域,以 Cortex-M 系列內核為例。

一、malloc 函數簡介

malloc的全稱是memory allocation,中文叫動態內存分配。

函數原型 void *malloc(unsigned int size),專業解釋還是套用百度百科:圖片對于malloc函數,應該所有嵌入式工程師都知道,即便沒用過也都聽過,通過上面簡單的說明,也都能夠知道是干什么用的。

注意上面紅色框框部分,malloc開辟的是連續的空間,返回的是一個地址,當內存不使用,需要使用free()函數釋放內存。

二、malloc 之于單片機

在我們的單片機程序設計中,大都使用的C語言,當然可以使用 malloc 函數,但是有很多人并不能夠真正的理解它。

要理解單片機系統中的 malloc函數 ,首先必須了解動態分配的內存是在什么地方呢!

2.1 malloc 函數申請的內存在哪里?

也許大部分人知道在堆中!是的,在堆中沒錯。

那么接著問題,堆在單片機的什么地方呢?具體地址是多少呢?

要了解這個問題,就得了解內核的數據存儲方式,我們以常用的STM32為例,我在下面這篇博文詳細的介紹過STM32的內存管理(如果不懂的建議先看一下這篇博文):

STM32的內存管理相關(內存架構,內存管理,map文件分析)

先簡單了解下單片機的堆棧,文中有如下說明:圖片

如果通過上面推薦的博文理解了內存分配,那么我們就可以得到如下結論,可以知道 malloc 申請空間的準確地址了:圖片

2.2 用與不用malloc的區別

知道了malloc申請空間在單片機中的地址,我們再來看一下用于不用的區別。

一般在我們的設計中,函數中可能會初始化一些臨時變量,如果是一個數組,那么他也會申請一段內存空間,我們通過一張圖來看看使用臨時變量與malloc 的區別:圖片

解釋到這里,相信大家對在單片機上使用 malloc 有了一個更深的認識。他所存放的空間與我們經常局部變量的空間是不同,而且我們也知道了在什么位置。

至于單片機用還是不用 malloc函數?別急,我們還得往下面分析分析。

三、malloc可能遇到的問題

還是官方的百度百科里面介紹malloc的工作機制時候,有下面的說明:圖片注意圖中畫紅色的部分,簡單解釋就是,使用 malloc 函數多了以后,會產生很多的內存碎片,白白浪費內存。

3.1 內存碎片

什么是內存碎片是什么?

這種專業的術語還得靠萬能的百度(雖然百度百科的解釋針對的是大范圍的,但是對于單片機來說其實是一樣的):圖片

系統中所有的不可用的空閑內存就是內存碎片。

那么 內存碎片是什如何產生的?

在上圖中其實有碎片是如何產生的說明,內部碎片是因為處理器的體系結構,需要字節對齊,比如我們在單片機中,常有4字節對齊,8字節對齊,不要說這個也不知道,我隨便打開一個 STM32L051 的啟動文件說明(GCC環境下的鏈接文件):圖片

按照這個啟動文件,我們也應該能知道,堆棧內存空間是需要8字節對齊的,那么我們在STM32上使用 malloc 分配的內存空間是8字節對齊的,即便你用不上8個字節,系統也會給你對齊補上。

說到這個,正好了可以說明我們內存碎片產生的第一種情況,內部碎片的產生:圖片那么外部碎片的產生,我們也可以用圖形來表示:圖片隨著內存不斷被分配和釋放,整個內存區域會產生越來越多的碎片,因為在使用過程中,申請了一些內存,其中一些釋放了,導致內存空間中存在一些小的內存塊,它們地址不連續,不能夠作為一整塊的大內存分配出去,系統中還有足夠的空閑內存,但因為它們地址并非連續,不能組成一塊連續的完整內存塊,會使得程序不能申請到大的內存。

在我們使用的單片機上,碎片產生問題尤為明顯,平時接觸不到,那是因為一般學習測試不會遇到復雜的項目。

3.2 內存管理

使用 malloc 會產生碎片,那么有什么辦法可以解決這個問題?

當然是有的,那就是內存管理。

內存管理就是為了解決上面提到的內存碎片問題,如何高效,快速的分配,并且在適當的時候釋放和回收內存資源。

對于單片機來說,如果你有能力是可以自己設計內存管理的方式。

如果使用嵌入式操作系統比如 FreeRTOS、RT-Thread 的話,他們內核是自帶內存管理的,本文并不會討論他們具體是如何內存管理的,但是有必要了解一下操作系統的思路。

以 FreeRTOS 為例子說明:

在 FreeRTOS 中有一個宏定義configTOTAL_HEAP_SIZE

操作系統首先向系統申請了一塊大的內存,這塊內存內存由操作系統自己的內存管理方式,對于FreeRTOS而言有5種內存管理方式:

我們在設計的時候可以自己選擇使用哪一種

對于申請的這塊內存由操作系統自動管理,FreeRTOS操作系統創建的任務,任務棧使用的就是這一塊內存,同時使用pvPortMalloc函數申請動態內存,也會從這一塊內存中分配,因為他有一套完善的內存管理方式,所以相對我們直接使用 malloc來說,他能夠很好的處理系統內存碎片的問題。

既然說到這里,額外的一個問題,就是 FreeRTOS configTOTAL_HEAP_SIZE定義額這塊內存處于單片機內存那個部分呢?

這就可以看我的又一篇博文:嵌入式RTOS的 任務棧 和 系統棧

FreeRTOS申請的內存是屬于.bss段的,位置如下圖所示:圖片

對于單片機使用的嵌入式操作系統來說,他們有自己的內存管理方式,也會提供對于的動態內存申請結構,這時候我們使用操作系統提供的 malloc 接口函數,可以很好的避免內存碎片的產生。

注意!!單片機用了有內存管理的操作系統,系統會提供對于的 API,比如 FreeRTOS 的 pvPortMalloc 函數,RT-Thread 的 rt_malloc 函數。如果使用 C 庫的 malloc,還是會從系統堆里面申請內存!!

對于高端的單片機,有 MMU(內存管理單元) 模塊,比如 Cortex-A 系列,有了MMU就能跑linux,那么內存管理也是必備。

四、結語(用還是不用?)

本文算是詳細分析了一下 malloc 函數在單片機上的使用效果,我們知道了 malloc 函數使用申請了內存空間在哪里,我們也知道了內存碎片是如何產生的。

回到我們最初的問題,單片機領域,用還是不用 malloc 函數?

看完文章這個問題估計都不需要我直接回答了:

從項目復雜程度來說:

如果跑裸機 做些小項目,如果沒有自己的內存管理方式不是必要都不建議使用,同時為了節約內存,可以把heap設置成很小(留一點給可能調用的C庫函數會用到)。

如果跑操作系統,操作系統有完善的內存管理,可以痛快的使用操作系統的malloc接口函數。 但是如果做些小項目,也是可以不用的。

如果跑裸機 做些大項目???? 我個人不太建議……

從使用的芯片RAM大小來說:

如果你選用的芯片內存比較小,10多K甚至幾K,還是用靜態內存局部變量把,因為能夠使用小內存的項目也不會太復雜,比如物聯網傳感器單品項目。

如果選用的芯片內存比較大上了 MB, 那么還是可以嘗試使用 malloc 動態內存分配的,但是前提還是得有內存管理。

但是最后還是得說一下,隨著現在的單片機發展,內存越來越大,雖然單片機小項目不建議使用 malloc 函數,但是我們上了操作系統以后,要學會去使用動態內存分配,因為當以后做的項目越來越復雜,線程越來越多,我們定義的局部變量越來越多,即便我們可以繼續增大系統 棧 的大小,但是這終究不是一種合理的解決方式。我們應該要學會合理的使用動態內存申請,為了以后向更高的地方前進 ~

沒有必要鉆牛角尖,如果項目簡單但就是想用。比如我就一個函數使用malloc 申請動態內存,沒有內存管理,我就是用了怎么地? 這種情況用不用都一樣,看自己高興,沒有必要糾結!

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6043

    文章

    44621

    瀏覽量

    638570
  • 嵌入式
    +關注

    關注

    5092

    文章

    19178

    瀏覽量

    307691
  • 函數
    +關注

    關注

    3

    文章

    4346

    瀏覽量

    62973
  • RTOS
    +關注

    關注

    22

    文章

    819

    瀏覽量

    119889
  • malloc
    +關注

    關注

    0

    文章

    53

    瀏覽量

    82
收藏 人收藏

    評論

    相關推薦

    淺談 malloc 函數單片機上的應用

    聊聊 malloc函數單片機程序設計中怎么使用
    的頭像 發表于 05-18 09:35 ?2483次閱讀
    淺談 <b class='flag-5'>malloc</b> <b class='flag-5'>函數</b>在<b class='flag-5'>單片機</b>上的應用

    求助:如何在STM32單片機程序中使用atoi()函數

    何在STM32單片機程序中使用atoi()函數
    發表于 02-05 18:39

    在Keil Arm中使malloc函數的方法是什么?

    在Keil Arm中使malloc函數的方法是什么?需要經歷哪幾個步驟?
    發表于 07-01 08:45

    何在單片機上也可正常使用動態內存分配

    51單片機內存動態分配序言最近玩51單片機碰到一個問題,51中malloc函數并不能像在PC上一樣正常運行,這涉及到了內存池的概念。下面就來演示一下如
    發表于 11-19 07:36

    在AVR單片機中使用printf函數

    Pro2、程序編寫要想在AVR單片機中使用printf函數,首先得包含頭文件,其次,得在函數中定義put...
    發表于 11-23 06:29

    何在STM8單片機中使用printf函數功能?

    何在STM8單片機中使用printf函數功能?
    發表于 12-01 07:19

    怎樣去解決單片機使用malloc產生內存泄露的問題呢

    為什么單片機使用malloc會導致內存泄露呢?怎樣去解決單片機使用malloc產生內存泄露的問題呢?
    發表于 01-27 06:23

    51單片機使用malloc函數總是分配不到空間的原因?

    51單片機使用malloc函數總是分配不到空間
    發表于 10-28 07:45

    如何使用單片機系統重寫printf函數

    本文檔的主要內容詳細介紹的是如何使用單片機系統重寫printf函數
    發表于 07-23 17:37 ?1次下載
    如何使用<b class='flag-5'>單片機</b>系統重寫printf<b class='flag-5'>函數</b>

    分享可應用于單片機的內存管理模塊mem_malloc

    本次給大家分享一位大佬寫的應用于單片機內存管理模塊mem_malloc,這個mem_malloc的使用不會產生內存碎片,可以高效利用單片機ram空間。 mem_
    的頭像 發表于 06-25 08:54 ?3081次閱讀
    分享可應用于<b class='flag-5'>單片機</b>的內存管理模塊mem_<b class='flag-5'>malloc</b>

    單片機 keil c語言字符比較函數的使用 使用strcmp();

    單片機 keil c語言字符比較函數的使用 使用strcmp();strcmp()的介紹、32單片機中的使用示例注意事項strcmp()的介紹、這是菜鳥教程的介紹:C 庫函數 int
    發表于 11-21 15:06 ?17次下載
    <b class='flag-5'>單片機</b> keil  c語言字符比較<b class='flag-5'>函數</b>的使用 使用strcmp();

    記錄單片機使用malloc產生內存泄露的問題及解決方法

    項目場景:單片機使用malloc產生內存泄露的問題問題描述:bug1:創建了一個結構體指針,通過malloc動態開辟內存的方式開辟了一段內存空間,然后進行寫入數據修改數據的操作,但是下面的代碼會導致
    發表于 12-03 10:21 ?8次下載
    記錄<b class='flag-5'>單片機</b>使用<b class='flag-5'>malloc</b>產生內存泄露的問題及解決方法

    何在Vitis HLS GUI中使用庫函數

    Vitis? HLS 2023.1 支持新的 L1 庫向導,本文將講解如何下載 L1 庫、查看所有可用功能以及如何在 Vitis HLS GUI 中使用庫函數
    的頭像 發表于 08-16 10:26 ?1257次閱讀
    如<b class='flag-5'>何在</b>Vitis HLS GUI<b class='flag-5'>中使</b>用庫<b class='flag-5'>函數</b>?

    單片機用按鈕中斷函數

    單片機用按鈕中斷函數? 單片機中斷是一種能夠使單片機響應外部信號的機制,這種機制允許單片機在處理其他任務時去響應中斷信號,從而提高
    的頭像 發表于 09-01 10:17 ?1614次閱讀

    malloc跟free的源碼分析

    malloc 本文梳理了一下malloc跟free的源碼。malloc()函數在源代碼中使用宏定義為public_
    的頭像 發表于 11-09 11:39 ?1747次閱讀
    克拉克百家乐官网的玩法技巧和规则 | 香港六合彩大全| 百家乐官网娱乐开户| 网络百家乐官网怎样出千| 百家乐有人赢过吗| 百家乐策略介绍| OK娱乐城| 百家乐官网视频游戏冲值| 2024属虎人全年运势| 威尼斯人娱乐城反水| 蒙山县| 江山百家乐官网的玩法技巧和规则 | 蓝盾百家乐的玩法技巧和规则| 百家乐备用网址| 嫩江县| 百家乐官网赌博软件下载| 百家乐视频官方下载| 全讯网开奖直播| 百家乐官网输一压二| 百家乐官网翻天超清| 威尼斯人娱乐城首存优惠| 在线百家乐官网大家赢| 百家乐娱乐城新闻| 92棋牌游戏| 百家乐官网博赌场| 威尼斯人娱乐城轮盘| 百家乐官网游戏机在哪有| 网络百家乐金海岸破解软件| 皇冠足球即时比分| 百家乐官网筹码皇冠| 富二代百家乐官网的玩法技巧和规则| 百家乐官网投注| 二八杠单机游戏| 百家乐官网平台凯发| 金牌百家乐的玩法技巧和规则| 香港六合彩的开奖结果| 粤港澳百家乐官网娱乐平台| 大上海百家乐的玩法技巧和规则 | 网上百家乐注册彩金| 去澳门赌博| 网上百家乐骗人的|