概述:在嵌入式体系中,程序终极是要放置在内存中运行的,程序的几个段,终极会转化为内存中的几个区域。深入了解这些底层的东西有助于编写高效的代码,加快调试研发。cms.com&kwtype=0&q=dedecms" target="_blank">dedecms.com&kwtype=0&q=c%25e8%25af%25ad%25e8%25a8%2580" target="_blank">c语言可执行程序的内存布局如次图所示: dedecms.com&kwtype=0&q=c%25e8%25af%25ad%25e8%25a8%2580" target="_blank">c语言程序"在内存中,从盆地址到高地址,依次是只读段,读写段,未初始化数据段,堆段,栈段。映像文件中将包罗代码段,只读数据段以及读写数据段,未初始化数据段将在程序初始化阶段开辟,仓库将在程序运行时动态开辟。只读区包括了代码和只读数据,在内存区域中,代码段和只读数据段的存放情势基本没区分。对于程序运行时的内存施用,堆和栈通常为相向扩大的。堆的分配由程序决议,栈由编译器管理。在实际的体系中,程序有载入和运行两个概念。嵌入式体系由两种内存,一种是可以固化只读的内存(如ROM,NOR FLASH),另一种是易失的可读写的内存(如,SRAM,SDRAM)。程序中的各个段也有需要固化和需要读写的。程序中的各个段必须载入到内存的患上当位置,程序才可以运行。在嵌入体系中,经过编绎的dedecms.com&kwtype=0&q=c%25e8%25af%25ad%25e8%25a8%2580" target="_blank">c语言程序可以通过操作体系运行,也可以在没有操作体系情况下运行。程序存放的位置和运行的位置凡是是纷歧样的。一般情况下经过编绎的程序储存在FLASH或硬盘中,在运行时需要将程序加载到RAM中,嵌入式体系的NOR FLASH和硬盘另有一定的差别,在硬盘的程序和须加载到RAM中才可以运行,可是在NOR FLASH中的程序可以通过XIP(eXcutive In Place) 的方式运行。在嵌入式体系中,C语言的运行包括3种类型:第一种是调试阶段的程序行,这个阶段程序程序的存放位置和运行位置是相同的;第二种是程序直接在FLASH中运行(XIP);第三种是将FLASH或硬盘中的程序完全加载到RAM中运行。在C语言的程序运行中,存在着两种基本的内存空间,一个是程序的储存空间,另一个是程序的运行空间。程序的储存空间包括代码段,只读数据段和读写数据段,程序的加载区域必须包括读写数据段和未初始化的数据段。如次表所示: 段 代码 只读数据 读写数据 未初始化的数据 程序的储存空间(ROM) 需要 不需要 程序的只读空间(RAM) 不需要 需要因为程序放入体系后,必须包括所有需要的信息,代码表示要运行的机器代码,只读数据和读写数据包罗程序中预先设置好的数据值,这些都是需要固化储存的,可是未初始化数据没有初值,因此只消标示它们的大小,而不需要储存区域。在程序运行的初始化阶段,将进行加载动作,其中读写数据段和未初始化数据段都是要在程序中进行“写”操作,因此没可能放在只读的区域必须放在RAM中,固然,程序也可以将代码和只读数据放在RAM中。在程序运行后,堆和栈将在程序运行历程中动态的分配和开释。1.RAM调试运行先先容一种特殊的运行方式,即在程序的调试阶段将主机的映像文件直接放置到目标体系的RAM中。在这类应用中,RAM既是程序的储存空间,也是程序的运行空间。在嵌入式体系中,这是一种常用的调试方式,而不是凡似的运行方式。在凡似的运行方式下,程序运行的起始地址一般没可能是RAM。RAM在掉电之后内部实质意义会丢失,因此体系上电的时辰,RAM中一般不会有有用的程序。可是在程序的调试阶段,可以将程序直接载入RAM,然后在RAM的程序载入地址入运行程序。这是一种相对简单的情势,因为代码段的储存地址和运行地址是相同的,都是RAM中的地址,在这类情况下,程序没有运行初始化阶段加载的问题。从主机向目标机载入程序的时辰,程序映像文件中代码段(code或text),只读数据段,读写数据段依次载入目标体系RAM的空间中。程序载入到目标机之后,将从代码区的地址起头敌对运行,在运行的初始化阶段,将开辟未初始化的数据区,并将其初始化为0,在运行机制时将动态开辟堆区和栈区。在没有操作体系的情况下,开辟内存的工作都是由编绎器天生的目标代码完成的,实现的原理是在映像文件中插手这些代码。首要工作包括:在程序运行时按照实际大小开辟未初始化的数据段;初始化栈区的指针,这个指针和物理内存的实际大小关于;在挪用相干函数(malloc ,free)时施用堆区,这些函数一般由挪用库函数关现。(注:程序直接载入RAM运行时,程序的加载位置和运行位置是相符的,因此不存在段复制的问题,需要在初始化阶段开辟未初始化区域,在运行时施用仓库。)2.固化程序的XIP运行固化应用是一种嵌入式体系常用的运行方式,其前提是目标代码位于目标体系ROM(FLASH)中。ROM中的区域包括映像文件的代码段(code 或text),只读数据段,读写数据段。以XIP(eXcutive In Place)方式运行程序时内存布局如图所示。 c语言程序"代码的运行也是在ROM(FLASH)中,因此,在编译历程中代码的储存地址和运行地址是相同的,因为上电时需要开始工作,因此该代位置通常为0X00。在这类应用中,一件重要的事情就是将已初始化读写段的数据从FLASH中复制到SDRAM中,因为已初始化读写段既需要固化,也需要在运行时个修改,因此这一步是必须有的,在程序的初始化阶段需要完成这一步。一般来说,在编译历程中需要定义读写数据段和未初始化段的地址。在程序中可获取这些地址,然后就可以在程序中插手复制的代码,实现读写段的转移。(注:程序在ROM或FLASH中以XIP情势运行的时辰,不需要复制代码段和只读数据段,可是需要在RAM中复制读写数据段,并另辟未初始化数据段)3.固化程序的加载运行某些时辰,在存放程序的位置是不能运行程序的,例如程序储存在不能以XIP方式运行的NAND——FLASH或硬盘中,在这类情况,必须将程序完全加载到RAM中才可以运行。固化程序加载运行的内存布局如图: c语言程序"依照这类程序运行程序,需要将FLASH中所有的内部实质意义全部复制到SDRAM或SRAM中。在一般情况下,SDRAM或SRAM的速率要快于FLASH。这样做的另一个好处是可以加快程序的运行速率。也就是说,即使FLASH可以运行程序,将程序加载到RAM中运行也另有一定的上风。这样做有另一个问题:代码段的载入地址和运行地址是不相同的,载入地址是在ROM(FLASH)中,可是运行的地址是在RAM中。对于这个问题,不同的体系在加载程序的时辰有不同的处理完成方式。(注:固化程序在加载运行时,需要复制代码段,只读数据段和读写数据段到RAM中,并另辟未初始化数据段,然后在RAM中运行程序(执行代码段))。另有另外一个问题:如何把代码拷到RAM中。在有操作体系的情况下,代码的复制工作是由操作体系完成的,在没有操作体系的情况下,处置惩罚方式相对复杂,程序需要自我复制。显然,这类方工棚实现的前提是代码最初放置在可以以XIP方式执行的内存中。程序自己复制的历程也是需要通历程序代码完成的,这时候需要程序中的代码按照将包罗自已的程序从ROM或FLASH中复制到RAM中。这是一个比力复杂的历程,程序的最前边部分是具备复制功效的代码。体系上电后,从ROM或FLASH起始地址运行,具备复制功效的代码将全部代码段和其它需要复制的部分代码复制到RAM中,然后跳转到RAM中重新执行程序。c语言程序运行总结在上男宠要先容了C语言运行时的内存施用情况。其存眷点是程序中首要的段,究竟上,程序可能不仅包括了上述首要段,还可能包括一些头信息。程序实际的运行也分为在操作体系下运行和直接运行等到情况。在具备操作体系的情况下,程序由操作体系加载运行,加载时辰可执行程序可所以一个文件,这个文件将包罗程序的首要段以及头信息。对于linux操作体系,目标程序是可执行的ELF(Executable and Linking Format)格式;对于需要在体系中直接运行的程序,目标程序应该是纯粹的二进制代码,载入体系后,直接转到代码区地址运行。究竟上,无论运行环境如何,C语言程序在运行时所进行的动作都是近似的。程序在准备起头运行的时辰,以下几个前提都是必不可少的:1.代码段必须位于可运行的储存区。2.读写数据段必须在可以读写的内存中,而且必须经过初始化国。3.未初始化数据段必须在可以读写的内存中开辟,并被告清空。对于第1点,代码段要是位于可以运行的储存区域中(如NOR FLASH或RAM),它就不需要加载,可以直接运行;要是代码段位于不能运行的储存区域中(如NAND FLASH或硬盘),它就必须被加载到RAM中运行。
|