一、嵌入式内存分段整体规则(按地址从低到高)

        嵌入式系统内存按 “功能 + 属性” 划分为 6 个核心段,地址从低到高依次分布,各段职责与存储对象明确,具体规则如下表:

地址范围段类型(Segment)对应段标识 / 关键字核心存储内容
低地址代码段(Code Segment).text编译后的机器指令、程序执行逻辑、#define定义的常量
常量段(Const Segment).rodata字符串常量(如"hello")、数字常量(如const int a=10)、const修饰的全局变量
全局 / 静态段(Global/Static Segment).bss.data.bss:未初始化的全局 / 静态变量、初始化为 0 的全局 / 静态变量
.data:已初始化(非 0)的全局 / 静态变量
堆段(Heap Segment)无固定标识开发者通过malloc手动分配的动态内存、需手动free释放的内存
高地址栈段(Stack Segment)无固定标识局部变量(如函数内int x=5)、const修饰的局部变量、函数形参、函数返回值

关键地址增长特性

  • 堆段:从低地址向高地址增长,由隐式指针跟踪分配边界;
  • 栈段:从高地址向低地址增长,遵循 “先进后出(FILO)” 规则,与数据结构中的 “栈” 逻辑一致。

二、各段核心属性与物理存储

不同段的读写权限、初始化方式、物理位置差异显著,直接影响嵌入式系统的资源占用与运行效率,具体细节如下:

1. 代码段(.text)

  • 核心属性
    • 权限:只读 + 可执行(不可修改,防止程序指令被意外篡改);
    • 初始化:由编译器将 C/C++ 代码编译为机器指令后生成,无需手动干预;
    • 物理存储:固定存于Flash( ,因代码无需运行中修改,且 Flash 非易失性可长期保存程序。
  • 典型场景:函数体逻辑(如void init(void)的指令)、程序主流程(main函数指令)。

2. 常量段(.rodata)

  • 核心属性
    • 权限:只读(运行中不可修改,若强行修改会触发硬件 / 软件保护);
    • 初始化:编译时由编译器将常量数据(如字符串、const全局变量)打包生成;
    • 物理存储:仅存于Flash,嵌入式系统中所有 “只读(RO)” 数据均不占用 SRAM(静态存储器),避免宝贵的 SRAM 资源浪费。
  • 易混淆点:函数内的字符串常量(如char* s="test")也存于.rodata,而非栈段;const局部变量则存于栈段(仅编译期限制修改,物理位置在 SRAM)。

3. 全局 / 静态段(.bss + .data)

(1).bss 段
  • 核心属性
    • 权限:可读可写(运行中可修改变量值,如int g_val; g_val=10;);
    • 初始化:不占用 BIN/ELF 文件空间,程序启动时由启动代码自动清零(无需开发者手动初始化);
    • 物理存储:仅存于SRAM,因全局 / 静态变量需运行中快速访问,SRAM 无需刷新、读写速度远快于 Flash。
  • 包含对象:未初始化的全局变量(如int g_uninit;)、初始化为 0 的静态变量(如static int s_zero=0;)。
(2).data 段
  • 核心属性
    • 权限:可读可写(运行中可修改,如int g_init=5; g_init=8;);
    • 初始化:占用 BIN/ELF 文件空间,编译时将初始值写入文件,程序启动后从 Flash 加载到 SRAM;
    • 物理存储:运行时存于SRAM(保证访问速度),初始数据备份于 Flash(非易失性保存)。
  • 关键影响:若全局 / 静态变量初始值非 0(如uint8_t buf[256*1024]={1};),会直接导致 BIN 文件增大 —— 因.data段需存储完整的初始化数据。

4. 堆段(Heap)

  • 核心属性
    • 权限:可读可写(动态分配的内存可自由修改,如char* p=malloc(10); p[0]='a';);
    • 初始化:开发者通过malloc/calloc手动初始化(如int* arr=malloc(4*5);),需通过free手动释放;
    • 物理存储:仅存于SRAM,因动态内存需快速读写,且运行中需灵活调整大小。
  • 风险点:未及时free会导致内存泄漏,长期运行会耗尽 SRAM;频繁分配 / 释放可能产生内存碎片,导致后续malloc失败(即使总剩余内存足够)。

5. 栈段(Stack)

  • 核心属性
    • 权限:可读可写(局部变量可修改,如void func(){int x=3; x=5;});
    • 初始化:由编译器自动管理,变量进入作用域时自动分配栈空间,离开作用域时自动释放(无需手动操作);
    • 物理存储:仅存于SRAM,栈访问依赖 CPU 寄存器(如栈指针 SP),速度极快。
  • 关键限制
    • 栈空间大小固定(由链接脚本配置,如STACK_SIZE = 0x1000),若局部变量过大(如char buf[1024*1024];)或递归调用过深,会导致栈溢出(程序崩溃);
    • 作用域限制:栈变量离开定义范围后即失效(如函数返回后,其内部局部变量地址变为 “无效地址”)。

三、段相关开发实践要点

结合嵌入式系统 “资源受限(SRAM/Flash 容量小)” 的特点,段的合理使用直接决定系统稳定性与资源利用率,核心实践要点如下:

1. 避免 BIN 文件膨胀:优先用.bss 段存大缓冲区

若需定义大缓冲区(如 256K/512K),避免使用.data段(如uint8_t buf[512*1024]={0};)—— 会导致 BIN 文件增大 512K;应定义为未初始化变量(uint8_t buf[512*1024];),使其进入.bss段,不占用 BIN 空间,仅运行时占用 SRAM。

2. 减少 SRAM 占用:只读数据放入.rodata

  • 全局常量(如配置参数const int MAX_LEN=1024)、固定字符串(如日志格式const char* LOG_FMT="[%s] %s")需加const修饰,确保进入.rodata段(存于 Flash),不消耗 SRAM;
  • 避免将 “无需修改的数据” 定义为全局变量(如int g_fixed=10),应改为const int g_fixed=10,节省 SRAM。

3. 栈段使用禁忌:不定义过大局部变量

  • 函数内避免定义大数组(如void func(){char big_buf[64*1024];}),若需大缓冲区,优先用malloc(堆)或全局.bss变量;
  • 递归函数需控制深度(如递归层级不超过 100),防止栈溢出,可改用迭代实现。

4. 堆段使用原则:减少动态分配,优先静态内存池

  • 嵌入式系统中,堆的malloc/free易导致内存碎片,关键场景(如实时控制)建议用 “静态内存池” 替代(预先分配一块连续 SRAM,手动管理分配 / 释放);
  • 若使用堆,需确保malloc返回值非NULL(判断内存分配是否成功),且配对使用free(避免泄漏)。

5. 链接脚本配置:明确段的内存分配

通过链接脚本(.ld 文件)指定各段的物理地址与大小,避免段重叠(如堆与栈重叠导致内存 corruption),示例配置:

/* 定义Flash和SRAM地址范围 */
MEMORY {FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 1024K  /* 代码段、常量段存于此 */SRAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 128K   /* .bss、.data、堆、栈存于此 */
}/* 分配各段到指定内存 */
SECTIONS {.text : { *(.text) *(.rodata) } > FLASH  /* 代码段+常量段放入Flash */.data : { *(.data) } > SRAM AT > FLASH   /* .data初始值存Flash,运行时加载到SRAM */.bss  : { *(.bss) } > SRAM               /* .bss直接放入SRAM */heap_start = .;                          /* 堆起始地址(.bss结束后) */stack_start = ORIGIN(SRAM) + LENGTH(SRAM);/* 栈起始地址(SRAM最高地址) */
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96466.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96466.shtml
英文地址,请注明出处:http://en.pswp.cn/web/96466.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开发避坑指南(45):Java Stream 求两个List的元素交集

需求 java 中如何用stream求两个List元素的交集&#xff1f; 代码实现 直接上代码 public class ListTest {public static void main(String[] args) {List<Integer> list1 new ArrayList<>();list1.add(1);list1.add(2);list1.add(3);List<Integer> list2 …

gitlab流水线与k8s集群的联通

gitlab流水线与k8s集群的连接&#xff0c;首先是通过gitlab-ci.yml文件中的命令&#xff0c;通过runner执行器实例运行对应的kubectl命令实现的。 那么runner执行器实例执行器如何执行kubectl命令&#xff0c;执行环境的配置&#xff0c;kubectl命令如何与k8s集群互认&#xff…

【Linux】常用命令速查表

Linux 常用命令速查表查看进程内存映射pmap -x <pid> # 查看进程的内存映射信息查看系统架构uname -m # 查看操作系统架构&#xff08;x86_64 / arm64 等&#xff09;磁盘与文件du -sh /home/* # 查看 /home 下每个用户目录的大小&#x…

Windows下编译SLEPc

本文记录在Windows下编译SLEPc的流程。 零、环境 操作系统Windows 11VS Code1.92.1MSYS2msys2-x86_64-20250830 一、安装依赖 1.1、依赖 首先&#xff0c;下载并安装MSYS2&#xff0c; 打开MSYS2 MINGW64控制台&#xff0c;运行以下命令安装依赖包&#xff0c; pacman -S …

运动生理实验室解决方案 人体生理实验整体解决方案

&#xff08;一&#xff09;、硬件参数 集成化折叠式无创型生理实验平台&#xff1a;1.1、 集成化设计:至少包含设备操作台、可收纳式交互实验桌、可收纳式检查床、生物信号 采集处理系统、计算机工作站集成于一体的高度集成设计&#xff1b;&#xff08;o561-6o623…

Axure RP 9 最新版安装包+安装步骤Win系统适用(附安装包)

Axure RP 9​ 是一款专业的 ​原型设计工具&#xff0c;主要用于 ​网站、APP、软件等产品的界面设计和交互原型制作。 一、准备工作 ​下载好安装包​ Axure RP 9安装包下载&#xff1a;https://pan.quark.cn/s/bc2b35011106 二、开始安装 第一步&#xff1a;双击运行安装包…

AutoMQ 亮相首尔:KafkaKRU 分享日志流处理新思路

全球 Kafka 社区都在关注 AutoMQ&#xff01;凭借在 Kafka 生态的独特创新&#xff0c;AutoMQ 深受 Kafka 用户喜爱&#xff0c;已成为众多企业和开发者的首选实时数据解决方案。昨天&#xff0c;我们非常高兴看到来自韩国的 KafkaKRU 核心社区在首尔举办第2届官方线下交流会。…

从零开始使用 axum-server 构建 HTTP/HTTPS 服务

axum-server 是 Rust 生态中为 axum 框架设计的高性能服务器实现&#xff0c;基于 hyper&#xff08;底层 HTTP 引擎&#xff09;和 tower&#xff08;服务抽象&#xff09;构建&#xff0c;支持 HTTP/1、HTTP/2 及 HTTPS。本教程将从环境准备到实战功能&#xff0c;一步步带你…

电路运行的核心-RTC

1. 时钟芯片是什么&#xff1f;时钟芯片&#xff0c;更准确的名称是实时时钟芯片&#xff0c;英文是 Real-Time Clock&#xff0c;简称 RTC。它是一个专用的集成电路&#xff0c;其核心功能是追踪时间和日历。你可以把它想象成电子设备里的一个“电子表”或“日历钟”。关键特性…

AR消防头盔:火场救援的智能“透视眼”

在浓烟弥漫、能见度几乎为零的火场中&#xff0c;消防员们依靠什么来精准掌握队友的位置和状态&#xff1f;答案是AR智能消防头盔&#xff08; www.teamhelper.cn &#xff09;。这种头盔通过多种定位技术的融合&#xff0c;为消防员提供了强大的团队协作和指挥协同能力&#x…

基于大模型的个性化推荐系统实现探索与应用

前言 如果你一直在跟着Fanstuck博主的脚步探索AI大模型的相关内容&#xff0c;从最初的大模型Prompt工程解析&#xff0c;DeepSeek全面解析&#xff0c;到实际的私有化大模型开发部署&#xff0c;再到深入NL2SQL、知识图谱大模型和ChatBI等更高阶应用.我是Fanstuck&#xff0c…

【已解决】Echarts 力学布局图谱切换图例的时候线条残留在了画布上

在用Vue3封装 ECharts 的力导向图&#xff08;graph force&#xff09;时&#xff0c;我遇到一个问题&#xff1a;点击图例切换节点显隐后&#xff0c;线条残留在原位置&#xff0c;画布出现“脏线条”。&#xff08;问题如下&#xff1a;&#xff09;这个问题本质上是因为…&…

Vue动态实时字数限制

文章目录&#x1f680; Vue.js 动态实时字数限制指南1. 核心实现方法1.1 使用计算属性 (Computed Property)1.2 结合计算属性的 Setter/Getter1.3 使用监听器 (Watcher)1.4 使用自定义指令 (Custom Directive)1.5 原生 maxlength 属性结合 Vue2. 特殊场景处理2.1 处理粘贴操作2…

荣耀手机无法连接win11电脑,错误消息:“无法在此设备上加载驱动程序 (hn_usbccgpfilter.sys)。”解决方案

错误发生背景&#xff1a; 本人于2024年月底买了一部荣耀Magic7 RSR手机&#xff0c;当时在win10的rog电脑上可以正常连接&#xff0c;但是后面换了一个acer的win11电脑后&#xff0c;一开始可以正常连接&#xff0c;但是要我下载荣耀Hisuite&#xff08;荣耀手机助理&#xff…

springboot env 多环境配置入门与实战

Spring Boot3 Env 项目地址 https://gitee.com/supervol/loong-springboot-study &#xff08;记得给个start&#xff0c;感谢&#xff09; Env 概述 在 Spring Boot 3 开发中&#xff0c;多环境配置是核心能力之一&#xff0c;其目的是为不同场景&#xff08;如开发、测试、…

利用conda打包/复刻生信环境

01、写在前面 大家拿到自己的服务器(趁开学| 入手足够完成硕博生涯的生信环境)后可能需要安装很多的软件与包&#xff0c;Linux中许多包的安装依赖过多、安装复杂。而conda作为一个能够直接安装超过90%软件的"管家"&#xff0c;能够像Windows和手机中的应用商店那样…

数据分析:合并

&#x1f537; DA37&#xff1a;统计运动会项目报名人数&#xff08;仅输出有人报名的项目&#xff09;✅ 题目描述给定两个 CSV 文件&#xff1a;items.csv&#xff1a;包含项目信息&#xff08;item_id, item_name, location&#xff09;signup.csv&#xff1a;包含员工报名信…

高并发内存池(一):项目介绍和ThreadCache(线程缓存)实现

前言&#xff1a;本文将要介绍的高并发内存池&#xff0c;它的原型是Google的⼀个开源项⽬tcmalloc&#xff0c;全称Thread-Caching Malloc&#xff0c;近一个月我将以学习为目的来模拟实现一个精简版的高并发内存池&#xff0c;并对核心技术分块进行精细剖析&#xff0c;分享在…

RK3399平台ffmpeg-VPU硬编码录制USB摄像头视频、H264或MJPEG编码

文章目录 1 前言2 项目内容详细说明2.0 功能2.1 工程文件夹说明 3 代码3.1 CameraThread类3.1 CameraThreadImpl类 4 资源下载 1 前言 在某项目中需要在RK3399平台实现USB摄像头画面的实时预览、视频录制、拍照存储等功能。   先来看需要实现的最终效果。    ffmpeg USB摄…

解决蓝牙耳机连win11电脑画质依托答辩问题

以wh910n蓝牙耳机为例 设置-系统-声音-输出&#xff08;耳机&#xff09;-常规&#xff08;输出点不允许&#xff09;然后删除wh910n蓝牙设备 重新配对蓝牙耳机