单片机C语言:程序在内存中的分布
嵌入式工程师成长日记 2025-02-18

内存布局图:

来分析一下程序在内存中的分布情况:


假设这块长方形是一块虚拟的内存空间,那么它的大小有多大呢?有4G空间大小。


以32位操作系统为例,32位操作系统的最大寻址能力,也就是2的32次方字节,换算一下就是4个G大小。

我们大部分操作系统,拿到这一块4个G的内存空间之后都会帮做简单的划分。

比如第一部分拿出来留给内核来使用,至于这块空间是多大呢?不同的操作系统有不同的大小,Linux这个块空间分配了1G的大小空间,那么剩下的用户区就是3个G,而1G的内存空间这一块区域称为内核区,也就是内核空间。


内核空间主要存储以下内容:
1.内核代码
这是操作系统内核的可执行指令集,包含了实现进程管理、内存管理、设备驱动、文件系统等核心功能的代码,比如进程调度算法、内存分配与回收算法的代码。

2.内核数据结构
进程控制块(PCB):存储进程的各种信息,如进程ID、进程状态、优先级、程序计数器、寄存器值等,用于操作系统对进程进行管理和调度。

内存管理数据结构:像页表,用于实现虚拟地址到物理地址的映射,记录了进程的虚拟内存空间与物理内存页的对应关系;还有内存分配位图,用于标记物理内存中哪些页面已分配,哪些是空闲的。

文件系统数据结构:如索引节点(inode)表,存储了文件的元信息,包括文件的权限、所有者、大小、创建时间等,以及目录项结构,用于组织文件系统中的目录和文件。

3.内核栈
为内核线程和中断处理程序提供临时的存储区域,用于保存函数调用的返回地址、函数参数、局部变量等。比如在中断处理函数执行时,会将当前进程的相关寄存器值等压入内核栈,以便中断处理完成后能恢复到原来的执行状态。

4.共享数据区
用于内核与驱动程序以及不同内核模块之间共享数据和传递信息,比如内核与显卡驱动程序可能会通过共享数据区来传递显示参数、图形数据等。

5.设备驱动程序代码和数据
包含了各种硬件设备的驱动程序代码,以及驱动程序运行时所需的数据,如网卡驱动程序代码及网卡的配置信息、状态寄存器值等,使内核能够与硬件设备进行交互,实现设备的初始化、数据传输等操作。

主要看一下用户空间:
1.我们从最低位的地址0开始看起,有一段非常非常小的地址空间,它是系统保留区,它是0~255这么小的一块空间,这块空间可以忽略不计,这一块是保留区。

2.代码段,也叫文本段,存储着程序的可执行指令,是程序运行的核心部分。如C语言程序中函数的指令代码就存于此,通常为只读,防止程序运行时意外修改导致错误。


3.只读数据段,它存储我们程序中的常量,我们写的常量全部存储在这个段里面。


代码段和只读数据段,它们具有相同的读写属性,存的都是只读的数据。


4.初始化数据段,顾名思义就是存储我们系统中初始化的数据,也就是存储我们系统中已经初始化的全局变量。

5.未初始化数据段,.BSS未初始化数据段,里面存储的是我们未初始化的全局变量:包括初始化为默认值的全局变量,比如整形默认初始化是0,布尔类型默认初始化的false,这样的变量会存储在未初始化数据段里面。


6.堆区,堆中存放的是我们程序中动态分配的内存。堆栈之间还有一块数据区,这一块数据区叫做共享数据区。堆的内存如果增长的话,它是向上增长的,但是栈的内存它是向下增长的。


用于动态内存分配,由程序员通过malloc、new等操作申请和释放内存空间。

如int* ptr = (int*)malloc(sizeof(int));即在堆段分配了一块存储int类型数据的空间。


7.栈是程序运行中调用最频繁的区域。比如说存储函数的形参,局部变量。


总结一下:
用户空间分为代码段,只读数据段,初始化数据段和未初始化数据段,堆区,栈区。


.test代码,存储程序中可执行指令。
只读数据段,存的是程序中写的常量。
初始化数据段,存的是已经初始化的全局变量。
未初始化数据段,存储的是未初始化的全局变量。

堆区,存储程序运行中动态开辟的空间。
栈,存储的是函数形参,局部变量。


声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 【7.24 深圳】2025国际AI+IoT生态发展大会/2025全球 MCU及嵌入式技术论坛


  • 相关技术文库
  • C语言
  • 编程
  • 软件开发
  • 程序
  • 光立方程序编写步骤

    基于51单片机的4*4*4光立方程序实现原理及程序代码。LED光立方的复位电路、时钟电路、每层LED灯电路控制逻辑,系统总原理图,工作流程及相关C语言源码实现。希望能够对你学习了解LED光立方程序编写及LED立方实体制...

    昨天
  • 封装继承多态

    封装: 封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。被封装的对象通常被称为抽象数据类型。 封装的意义: 封装的意义在于保护或者防止代码(数据)被我们无意中...

    昨天
  • 封装是什么意思?

    即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中...

    昨天
  • 超声波模块测距51程序_单片机超声波测距c语言

    超声波检测原理 超声波测距的程序流程图 程序如下: //超声波模块程序 //超声波模块程序 //Trig = P2^0 //Echo = P3^2 #include #define uchar unsigned char #define uint unsigned int // void delay(uint z) {...

    07-01
  • 大佬带你看嵌入式系统,嵌入式系统该学习什么?

    嵌入式系统是当今的热门系统之一,在诸多领域,嵌入式系统都有所应用。为增进大家对嵌入式系统的认识,小编将为大家介绍嵌入式系统是一个什么样的专业,以及学习嵌入式系统该学习哪些内容。如果你对嵌入式系统具有...

    06-27
  • c51单片机编程要点总结

    c51单片机编程要点总结 1、头文件:#include (我用的是 STC 89C54RD+) 2、预定义:sbit LED = P1^0// 定义 P1 口的 0 位为 LED 注:“P1^0”这个写法,与 A51 不同(A51 是 P1.0),P1 是一组端口,端口号范围 0~7 注2...

    06-25
  • C语言基础知识点汇总

    总结C语言基础知识点

    06-23
  • Keil使用中的若干问题

      一、混合编程  1、模块内接口:  使用如下标志符:  #pragma asm  汇编语句  #pragma endasm  注意:如果在c51程序中使用了汇编语言,注意在keil编译器中需要激活Properties中的“Generate Assembler...

    06-23
  • ESP32-finsh

    esp32c2添加finsh实现了ping指令和AT指令解析

    06-13
  • 一文讲通C语言位域,快速掌握!

    在嵌入式系统的开发中,内存是最程序员非常需要关注的对象,尤其是MCU开发、网络协议解析、硬件寄存器操作等领域,能否对内存进行高效的利用和合理的管理,将直接影响程序的性能和硬件的稳定性。

    06-10
下载排行榜
更多
评测报告
更多
广告