内存、存储中(计算机、MCU)的引导流程、存储器
一、内存
- 栈区(stack):存放 非静态局部变量
- 堆区(heap):存放 malloc()、calloc() 、realloc()、free()等函数动态分配的数据 ——malloc() - C语言标准库中的函数
- 全局静态区:存放 静态局部变量、全局变量
- 代码区:存放 程序代码
- 栈区和堆区 存放 程序运行的动态数据
栈区(Stack)和堆区(Heap)是程序运行时在RAM(Random Access Memory,随机存取存储器)中划分的两个主要的内存区域,它们用于存储程序运行时的动态数据。
栈区:
- 栈是由编译器自动分配和释放的,用于存储局部变量、函数调用信息(如返回地址、参数)等。
- 栈具有自动管理的特点,函数调用时自动分配,函数返回时自动释放。
- 栈的内存空间相对较小,但访问速度快。
- 栈按照后进先出(LIFO,Last In First Out)的原则操作。
堆区:
- 堆是由程序员手动分配和释放的,通常使用如
malloc
、calloc
、realloc
和free
这样的函数(在C/C++中)。 - 堆用于存储动态分配的对象,其生命周期由程序员控制。
- 堆的内存空间相对较大,但访问速度较慢,因为分配和释放需要额外的管理开销。
- 堆按照自由可用的原则操作,分配的内存可以在任何时候释放。
注:虽然RAM是最常见的包含栈和堆的存储区域,但这并不意味着其他类型的存储器就不能有类似的概念。
eg:例如,某些嵌入式系统可能在非易失性存储器(如EEPROM或闪存)中模拟堆的行为,用于存储需要持久化的数据。但是,这种“堆”不会像RAM中的堆那样快速或灵活,而且可能受到写入次数的限制。
在讨论栈和堆时,我们通常指的是运行时动态分配的内存,而这几乎总是与RAM相关联,因为RAM提供了必要的速度和随机访问特性,这是栈和堆高效操作所必需的。
-
全局静态区(也称为全局区或静态区)
在程序的内存布局中主要包含两种类型的变量:
未初始化的全局变量和静态变量:这些变量在程序开始执行时会被自动初始化为零(或者说是它们数据类型对应的零值),并且存储在BSS(Block Started by Symbol)段中。
已初始化的全局变量和静态变量:这些变量在程序开始执行时已经被赋予了初始值,它们存储在数据段(Data Segment)中。
在现代计算机系统中,无论是BSS段还是数据段,它们都是位于RAM(Random Access Memory)中的。这意味着,全局静态区的变量最终是在RAM中存储的,尽管它们在物理存储器上的具体位置可能因操作系统和链接器的具体实现而异。1.BSS段:
BSS段通常不占用任何实际的磁盘空间,因为它只包含未初始化的变量,这些变量在加载到内存时会被初始化为零。当程序加载到内存中时,BSS段占用的内存空间会被清零。2.数据段:
数据段包含了初始化的全局变量和静态变量,以及常量字符串等。数据段在程序加载时就已经包含了初始化的数据,因此它在磁盘上和加载到内存中都会占据实际的存储空间。
总结来说,全局静态区确实是在RAM中,这是因为RAM提供了程序运行时所需要的高速随机访问存储能力,而静态区的变量需要在程序运行期间可供访问和修改。
-
代码区
代码区不直接位于RAM中,它通常位于ROM或者Flash Memory中。
在嵌入式系统中,如使用STM32微控制器的设备,代码区(包含程序指令)通常存储在非易失性存储器里,如Flash Memory,这是因为Flash Memory即使在电源关闭后也能保留数据,这对于存储程序代码是非常必要的。1.然而,对于某些系统架构,尤其是那些采用哈佛架构的处理器,如ARM Cortex-M系列,代码可以从Flash直接执行,而不需要先复制到RAM中。这是因为在哈佛架构中,指令和数据存放在不同的总线上,允许处理器同时访问指令和数据,从而提高性能。
2.但是,也有一些情况下代码会被加载到RAM中运行:
当系统需要频繁修改代码或执行非常快速的代码访问时,代码可能会被加载到RAM中。这是因为RAM提供比Flash更快的读取速度。
一些采用冯·诺依曼架构的处理器,如ARM Cortex-A系列,可能需要将代码从Flash加载到RAM中,然后从中执行,因为这些处理器不支持从Flash直接执行代码。
在现代计算机系统中,如个人电脑或服务器,代码通常首先从硬盘或固态硬盘加载到RAM中,然后由CPU执行。这是因为硬盘和固态硬盘提供了大容量的存储空间,而RAM提供了快速的数据访问速度,适合程序的运行。
总结来说,代码区的位置取决于具体的系统架构和硬件配置。在嵌入式系统中,代码区通常位于Flash Memory中,而在需要高性能或频繁代码修改的系统中,代码可能会被加载到RAM中运行。
二、从 存储 中,计算机、单片机的开机/执行程序 的引导流程
1、计算机引导流程
现代计算机的开机通常要经历一个复杂且精心设计的过程,这个过程叫做引导。引导是计算机启动和运行操作系统的初始步骤,它确保了系统能够正确地加载和执行所需的程序。
引导过程随CPU架构不同而不同,我们平常接触最多的是x86架构
CPU内部ROM(存储固定的指令)
内存中的存储介质选用的是RAM
磁盘模块代表的是持久化存储模块,其实和内存模块电路类似,采用了独立端口的EEPROM
目前我们的计算机总共有三块存储:
iRom:CPU内部很小的一块存储,只读;(该块存储器在出厂的时候已经把代码烧录好了,一般是不允许修改的;该存储器写入代码的功能主要是用于调用内存中的代码,然后执行)
内存(RAM):无法持久化保存数据,只有上电之后才能由程序修改;
硬盘(ROM):存放我们的自定义代码和数据。[目前硬盘大部分已经使用 EEPROM ]
引导程序 设计如下:
1. iRom负责将硬盘前32个寻址长度的程序加载到内存并跳转;
2. 硬盘前32个寻址长度负责加载(硬盘32个指令之后的)自定义程序并跳转;
-
最终(在内存中)执行自定义程序。
注:而硬盘前32个寻址地址存放的程序,我们就称之为引导程序,而这32个寻址地址,我们称之为引导区。
终端最终会显示自定义程序执行的内容
2. 单片机的引导流程
可以把单片机视为ROM和RAM都内置在MCU中 【相对于计算机少了一个硬盘】
只暴露一些输入输出总线接口和外部通信的设备。引导过程就相当于在ROM上直接执行程序,只有需要用到RAM时才会向RAM中写入数据。
51单片机的固定初始化流程
-
程序编译完成以后的汇编文件:
在ROM中,第一条指令:直接跳转到 单片机的固定初始化流程 ,当这段代码执行完毕后,最后一句代码就是跳转到 main函数入口,执行main主函数。
三、存储器和寄存器
1、存储器
存储器是计算机结构的重要组成部分。存储器是用来存储程序代码和数据的部件,有了存储器计算器才具有记忆功能
分为两大种:RAM(随机存取存储器) 、 ROM(只读存储器)
RAM -> 内存
* RAM提供了程序运行时所需要的高速随机访问存储能力
ROM -> 硬盘(一般用的较多的是flash [又名闪存,是可重复擦写的存储器] )
STM32:
在STM32中,芯片能访问的存储空间有多大,是由芯片的*地址总线的数量*决来定的,STM32芯片内部的地址总线为32根。所以STM32有*4G*的地址空间。(2的32次方)
ARM把可访问的存储器空间分成8个主要块,每个块为512MB。ARM 在对这 4GB 容量分块的时候是按照其功能划分,每块都有它特殊的用途。
在这8个Block里面,要特别注意Block0、Block1和Block2这3个块。因为其中包含了STM32芯片的内部 Flash、RAM和片上外设。
2、寄存器
寄存器是单片机内部一种特殊的存储器,可以实现对单片机各个功能的控制。
给已经分配好地址的有特定功能的存储器单元*取别名的过程*就叫*寄存器映射*。
注:寄存器映射在ST提供的头文件stm32f10x.h中已经通过预编译的形式完全映射好了,以后如果再操作某个特定外设的时候,就不用直接操作地址,直接操作对应的寄存器名就可以了。
eg:PA这组IO端口的映射
// 外设基址
#define PERIPH_BASE ((uint32_t)0x40000000)
// APB2外设的基址
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
// GPIOA 外设的基址
#define GPIOA_BASE (APB2PERIPH_BASE + d)
// 做了类型转换,地址仍然是GPIOA 外设的基址
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)