文章目录
前言
我们在实际嵌入式软件开发过程中,编译完代码之后会出现下图的样式,那这到底是指啥呢?
不必担心,走你~
一、text段(代码段)
1、详细介绍
a)功能
text段主要存储程序的可执行代码,即经过编译后的机器指令。这些指令是程序运行时处理器实际执行的操作,包括函数调用、算术运算、逻辑判断等。
b)特点
只读性: 一般情况下,text段是只读的,因为程序在运行过程中不应该修改自身的指令代码,以确保程序的稳定性和安全性。
共享性:多个进程可以共享同一个text段。由于代码在执行过程中不会被修改,所以多个进程可以同时运行相同的代码,而无需为每个进程都复制一份代码,从而节省内存空间。
c)代码示例
在一个简单的 C 语言程序中,函数的定义部分最终会被编译到text段中。例如:
#include <stdio.h>
// 这个函数的机器指令会存放在text段
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 5);
printf("The result is: %d\n", result);
return 0;
}
2、存储位置
在大多数嵌入式系统中,text段通常存储在非易失性存储器(如 Flash)中。这是因为 Flash 具有掉电不丢失数据的特性,适合存储程序代码。在程序运行时,text段会从 Flash 加载到内存(如 SRAM)中,以便处理器能够快速访问和执行。
二、data段(数据段)
1、详细介绍
a)功能
data段用于存储已初始化的全局变量和静态变量。这些变量在程序编译时就已经被赋予了初始值,并且在程序运行过程中需要保留这些初始值。
b)特点
可读写性: 与text段不同,data段是可读写的,因为程序在运行过程中可能需要修改这些变量的值。
占用存储空间: data段在程序加载时会占用一定的内存空间,因为需要将编译时确定的初始值从存储介质(如 Flash)复制到内存(如 SRAM)中。
c)代码示例
以下是一个包含已初始化全局变量的 C 语言程序示例:
#include <stdio.h>
// 这个全局变量会被存放在data段
int global_variable = 10;
int main() {
// 修改全局变量的值
global_variable = 20;
printf("The value of global_variable is: %d\n", global_variable);
return 0;
}
2、存储位置
data段的初始值通常存储在非易失性存储器(如 Flash)中,而在程序运行时,这些初始值会被复制到内存(如 SRAM)的可读写区域。这是因为 SRAM 具有更快的读写速度,适合程序在运行过程中对变量进行读写操作。
三、bss段(未初始化数据段)
1、详细介绍
a)功能
bss段用于存储未初始化的全局变量和静态变量。这些变量在程序编译时没有被赋予初始值,编译器只是为它们预留了内存空间。
b)特点
零初始化: 在程序加载时,bss段中的变量会被自动初始化为零值。这是因为在程序开始运行之前,系统会将bss段的内存区域全部清零。
不占用存储介质空间: bss段在存储介质(如 Flash)中不占用实际的存储空间,因为这些变量没有初始值,只需要在内存中预留空间即可。在程序加载时,系统会根据链接脚本中指定的bss段大小,在内存中分配相应的空间并清零。
c)代码示例
以下是一个包含未初始化全局变量的 C 语言程序示例:
#include <stdio.h>
// 这个全局变量会被存放在bss段
int uninitialized_global_variable;
int main() {
// 输出未初始化全局变量的值,应该为0
printf("The value of uninitialized_global_variable is: %d\n", uninitialized_global_variable);
return 0;
}
2、存储位置
bss段只存在于内存(如 SRAM)中,在存储介质(如 Flash)中没有对应的存储空间。因为这些变量的初始值都是零,所以不需要在 Flash 中存储初始值,只需要在内存中分配空间并清零即可。
四、内存布局及初始化过程
在程序启动时,会有一个内存初始化的过程,具体步骤如下:
1.加载text段:将text段从存储介质(如 Flash)加载到内存的指定位置,通常是只读区域。
2.复制data段:将data段从存储介质复制到内存的可读写区域,因为这些变量在程序运行过程中可能会被修改。
3.清零bss段:将bss段对应的内存区域全部清零,以确保未初始化的全局变量和静态变量初始值为零。
在链接脚本中,通常会对这些段进行明确的定义和分配,例如:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}
SECTIONS
{
.text :
{
*(.text)
*(.rodata)
} > FLASH
.data :
{
_sdata = . ; 数据段起始地址
*(.data)
_edata = . ; 数据段结束地址
} > SRAM AT > FLASH
.bss :
{
_sbss = . ; BSS段起始地址
*(.bss)
_ebss = . ; BSS段结束地址
} > SRAM
}
在这个链接脚本中,.text段被分配到 Flash 中,.data段和.bss段被分配到 SRAM 中,同时.data段的初始值存储在 Flash 中,在程序启动时会被复制到 SRAM 中。