我正在尝试用Rust编程裸机嵌入式系统。在C启动代码中通常做的一件事是对任何全局或静态未初始化变量的BSS段进行零初始化。
然而,在Rust中,我不知道如何创建任何全局或静态未初始化的变量(即使使用unsafe
代码)。换句话说,我不知道如何编写任何Rust代码,以便编译器将用某些东西填充BSS段。
我试过…
static BSS_Data: i32 = unsafe { core::mem::uninitialized() };
…但是编译器拒绝了。
是否有任何方法来编写Rust代码(unsafe
或其他),将导致一个填充的BSS段?在任何完全用Rust编写的程序中,BSS段是否保证始终为空?
static mut XYZ: [u8; 0xabc123] = [0; 0xabc123];
fn main() {
unsafe { println!("{}", XYZ[1000]); }
}
$ rustc bss.rs
$ readelf -SW bss | grep bss
[21] .tbss NOBITS 000000000004b178 04a178 000028 00 WAT 0 0 8
[28] .bss NOBITS 000000000004e038 04d038 abc220 00 WA 0 0 8
$ ./bss
0
.bss
段的目的是加速所有值为0的静态存储持续时间变量的初始化。但是也要保存NVM,因为在闪存中保存x字节的值0
然后逐个复制到RAM是没有意义的。
这个问题的解决方案可能是声明一个静态变量并显式地将其初始化为零。因为所有初始化为0的静态存储持续时间的变量最终都在.bss
中结束。
作为一个副作用,所有未初始化的静态存储持续时间变量也会在.bss
中结束。因为在C语言中(以及从C派生或受C启发的语言中),如果具有静态存储持续时间的变量没有由程序员显式初始化,则必须将其初始化为值0。
例如,这在C11标准6.7.9中有正式规定:
如果对象具有静态或线程存储持续时间显式初始化,然后:
-如果它有指针类型,它就是初始化为空指针;
-如果它是算术类型,它是初始化为(正或无符号)零;
.data
和.bss
初始化的伪代码示例。
关于不同内存类型和不同类型变量在嵌入式系统中的位置的更多信息。