.text 段的内存和.rodata的内存区别
结论
物理存储上:都存放在 Flash,地址连续、同一块物理存储芯片,硬件无分区隔离;逻辑 / 访问权限 / CPU 机制上:完全分开,用途、保护、加载规则不同。
一、物理层面(硬件 Flash)
- 同一片 Flash 存储颗粒
.text(Code)+.rodata(常量字符串 /const)+.data初始化副本 全部烧录在同一块 Flash,物理介质没有隔断,只是链接脚本分配了不同地址区间。 - 读操作硬件通路完全一样CPU 通过 Flash 控制器读取指令、读取常量数据,走同一套读取总线;Flash 硬件本身不区分这段存的是代码还是字符串。
- 擦写特性一致Flash 只能整块擦除、按页编程,不会区分
.text和.rodata区域。
简单说:硬件看不出两者区别,只是链接器人为划分地址区间。
二、逻辑、访问、权限上的本质区别(重点)
1. .text 段(程序代码)
存放:函数汇编指令、中断函数、运算逻辑
- CPU 访问方式:取指操作 I-FetchCPU PC 指针指向该区域,读取机器码执行;
- 访问权限:只读,禁止数据写访问多数单片机 MPU / 存储器保护单元会配置:.text 区域只允许指令读取,禁止普通数据读写;如果代码里指针强行修改 .text 地址,直接触发内存访问异常 HardFault;
- 内容:二进制机器指令,不能被代码当成普通数据遍历修改。
2. .rodata 段(只读常量)
存放:字符串字面量、const全局常量、只读查找表
- CPU 访问方式:数据读取 D-Fetch用普通指针、数组下标读取,不是 PC 取指令;
- 访问权限:同样只读,但权限属性是「只读数据区」;MPU 配置为允许数据读,不允许写,不允许当成指令执行;如果跳转到 rodata 地址当作函数执行,会取到乱码数据当指令,直接死机;
- 用途:纯数据,没有可执行指令。
三、举个直观例子
c
运行
const char log_str[] = "val=%d\n"; // 存在 .rodata void cal_coulometer(uint32_t vbat)// 函数指令存在 .text { unsigned int val=100; LOG(log_str,val); }- CPU 运行 cal_coulometer:PC 指针去
.text拿指令执行; - 打印时读取字符串:D 总线去
.rodata拿字符串字节;两块物理上挨在一起在 Flash,但 CPU 硬件层面区分「指令总线」「数据总线」访问。
四、补充两个容易混淆的点
- 会不会放到不同 Flash 分区?不会,普通 MCU 单块 Flash,链接脚本只是划分虚拟地址;只有带多块独立 Flash 芯片的高端芯片才会物理分开。
- 和 RAM 对比区分.text/.rodata 全程在 Flash,运行时不拷贝到 RAM;RW-data/ZI (.bss) 是运行时拷贝 / 清零到 RAM,物理介质完全不同。
总结
- 物理硬件:无区别,同一块 Flash,同一套读写电路;
- 逻辑 / CPU 总线 / 权限:有严格区分,一个是指令区,一个是只读数据区,不能混用
