13.4 C语言程序的运行
在嵌入式系统中,程序最终是要放置在内存中运行的,程序的几个段,最终会转化为内存中的几个区域。C语言可执行程序的内存布局如图13-5所示。
|
| (图13-5 C语言可执行程序的内存布局 |
在内存中,从低地址到高地址,依次是只读段、读写段、未初始化数据段、堆段、栈段。
映像文件中将包含代码段(Code)、只读数据段(RO Data)以及读写数据段(RW Data),未初始化数据段(BSS)将在程序的初始化阶段中开辟,堆栈在程序运行时动态开辟。
只读区(RO)包括了代码和只读数据,在内存区域中,代码段(Code)和只读数据段(Ro Data)的存放形式上基本没有区别。
对于程序运行时的内存使用,堆和栈一般是相向扩展的。堆的分配由程序决定,栈由编译器管理。
在以上概念中,只是一种内存分布,并没有考虑实际系统的情况。在实际的系统中,程序有载入和运行两个概念。嵌入式系统由两种内存,一种是可以固化只读的内存(如:ROM,Nor Flash),另一种是易失的可读写的内存(如:SRAM和SDRAM)。程序中的各个段也有需要固化和需要读写的。程序中的各段必须载入到内存的恰当位置,程序才可以运行。C语言各部分的需要固化和可写的情况如表13-2所示。
表13-2 C语言各部分的需要支持固化和可写的情况
|
段< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> |
需要固化 |
需要可写 |
|
代码(Code) |
是 |
否 |
|
只读数据(RO data) |
是 |
否 |
|
读写数据(RW data) |
是 |
是 |
|
未初始化数据(BSS) |
否 |
是 |
|
堆(heap) |
否 |
是 |
|
栈(stack) |
否 |
是 |
在嵌入式系统中,经过编译的C语言程序可以通过操作系统运行,也可以在没有操作系统的情况下运行。程序存放的位置和运行的位置通常是不一样的。
一般情况下,经过编译后的程序存储在Flash或者硬盘中,在运行时需要将程序加载到RAM中。嵌入式系统的Nor Flash和硬盘还有一定的差别,在硬盘的程序必须加载到RAM中才可以运行,但是在Nor Flash中的程序可以通过XIP(eXcutive In Place)的方式运行。
在嵌入式系统中,C语言程序的运行包括3种类型:第一种是调试阶段的程序运行,这个阶段程序存放的位置和运行的位置是相同的;第二种是程序直接在Flash中运行(XIP);第三种是将Flash或者硬盘中的程序完全加载到RAM中运行。
在C语言程序的运行中,存在着两个基本的内存空间,一个是程序的存储空间,另一个是程序的运行空间。程序的存储空间必须包括代码段、只读数据段和读写数据段,程序的加载区域必须包括读写数据段和未初始化数据段如表13-3所示。
表13-3 C语言各部分使用的存储空间
|
段 |
代码 |
只读数据 |
读写数据 |
未初始化数据 |
|
程序的存储空间(ROM) |
需要 |
不需要 |
|
程序的加载空间(RAM) |
不需要 |
需要 |
由于程序放入系统后,必须包括所有需要的信息,代码表示要运行的机器代码,只读数据和读写数据包含程序中预先设置好的数据值,这些都是需要固化存储的,但是未初始化数据没有初值,因此只需要标示它的大小,而不需要存储区域。
在程序运行的初始化阶段,将进行加载动作,其中读写数据和未初始化数据都是要在程序中进行"写"操作,因此不可能放在只读的区域内,必须放入RAM中。当然,程序也可以将代码和只读数据放入RAM。
在程序运行后,堆和栈将在程序运行过程中动态地分配和释放。