C程序的详细执行过程知识分享.doc

上传人:1595****071 文档编号:51510290 上传时间:2022-10-18 格式:DOC 页数:15 大小:378.50KB
返回 下载 相关 举报
C程序的详细执行过程知识分享.doc_第1页
第1页 / 共15页
C程序的详细执行过程知识分享.doc_第2页
第2页 / 共15页
点击查看更多>>
资源描述

《C程序的详细执行过程知识分享.doc》由会员分享,可在线阅读,更多相关《C程序的详细执行过程知识分享.doc(15页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、Good is good, but better carries it.精益求精,善益求善。C程序的详细执行过程-嵌入式C语言程序的运行2011-08-1615:05我们做C语言中这么多年,都知道这样一句话,C语言代码形成可执行程序,需要经过编译-汇编-链接三个阶段。背都背熟了,但是到底啥意思,每一步都会产生一些什么东西,很多人都不是太了解。今天就详细的来说说这个问题:先看下图,在这个图中,我详细的描述了,整个过程及中间的一些步骤:代码段,只读数据段,读写数据段,未初始化数据段属于静态区域。栈和堆属于动态区域。代码段,只读数据段和读写数据段将在连接之后产生,未初始化数据段将在程序初始化的时候开

2、辟,而堆和栈将在程序的运行中分配和释放。C语言程序分为映像和运行两种状态。在编译连接后形成的映像中,将只包含代码段,只读数据段和读写数据段。在程序运行之前,将动态生成未初始化数据段,在程序的运行时还将动态形成堆和栈区域。在嵌入式系统中,程序最终是要放置在内存中运行的,程序的几个段,最终会转化为内存中的几个区域。C语言可执行程序的内存布局如图13-5所示。图13-5C语言可执行程序的内存布局在内存中,从低地址到高地址,依次是只读段、读写段、未初始化数据段、堆段、栈段。映像文件中将包含代码段(Code)、只读数据段(ROData)以及读写数据段(RWData),未初始化数据段(BSS)将在程序的初

3、始化阶段中开辟,堆栈在程序运行时动态开辟。只读区(RO)包括了代码和只读数据,在内存区域中,代码段(Code)和只读数据段(RoData)的存放形式上基本没有区别。对于程序运行时的内存使用,堆和栈一般是相向扩展的。堆的分配由程序决定,栈由编译器管理。在以上概念中,只是一种内存分布,并没有考虑实际系统的情况。在实际的系统中,程序有载入和运行两个概念。嵌入式系统由两种内存,一种是可以固化只读的内存(如:ROM,NorFlash),另一种是易失的可读写的内存(如:SRAM和SDRAM)。程序中的各个段也有需要固化和需要读写的。程序中的各段必须载入到内存的恰当位置,程序才可以运行。C语言各部分的需要固

4、化和可写的情况如表13-2所示。表13-2C语言各部分的需要支持固化和可写的情况段需要固化需要可写代码(Code)是否只读数据(ROdata)是否读写数据(RWdata)是是未初始化数据(BSS)否是堆(heap)否是栈(stack)否是在嵌入式系统中,经过编译的C语言程序可以通过操作系统运行,也可以在没有操作系统的情况下运行。程序存放的位置和运行的位置通常是不一样的。一般情况下,经过编译后的程序存储在Flash或者硬盘中,在运行时需要将程序加载到RAM中。嵌入式系统的NorFlash和硬盘还有一定的差别,在硬盘的程序必须加载到RAM中才可以运行,但是在NorFlash中的程序可以通过XIP(

5、eXcutiveInPlace)的方式运行。在嵌入式系统中,C语言程序的运行包括3种类型:第一种是调试阶段的程序运行,这个阶段程序存放的位置和运行的位置是相同的;第二种是程序直接在Flash中运行(XIP);第三种是将Flash或者硬盘中的程序完全加载到RAM中运行。在C语言程序的运行中,存在着两个基本的内存空间,一个是程序的存储空间,另一个是程序的运行空间。程序的存储空间必须包括代码段、只读数据段和读写数据段,程序的加载区域必须包括读写数据段和未初始化数据段如表13-3所示。表13-3C语言各部分使用的存储空间段代码只读数据读写数据未初始化数据程序的存储空间(ROM)需要不需要程序的加载空间

6、(RAM)不需要需要由于程序放入系统后,必须包括所有需要的信息,代码表示要运行的机器代码,只读数据和读写数据包含程序中预先设置好的数据值,这些都是需要固化存储的,但是未初始化数据没有初值,因此只需要标示它的大小,而不需要存储区域。在程序运行的初始化阶段,将进行加载动作,其中读写数据和未初始化数据都是要在程序中进行“写”操作,因此不可能放在只读的区域内,必须放入RAM中。当然,程序也可以将代码和只读数据放入RAM。在程序运行后,堆和栈将在程序运行过程中动态地分配和释放。13.4.1RAM调试运行本节介绍程序的一种特殊的运行方式,即在程序的调试阶段将主机的映像文件直接放置到目标系统的RAM中。在这

7、种应用中,RAM既是程序的存储空间,也是程序的运行空间。在嵌入式系统中,这是一种常用的调试方式,而不是通常的运行方式。在通常的运行方式下,程序运行的起始地址一般不可能是RAM。RAM在掉电之后内容会丢失,因此系统上电的时候,RAM中一般不会有有效的程序。但是在程序的调试阶段,可以将程序直接载入RAM,然后在RAM的程序载入地址处运行程序。嵌入式系统RAM中的调试程序的内存布局如图13-6所示。图13-6RAM中的调试程序的内存布局这是一种相对简单的形式,因为代码段的存储地址和运行地址是相同的,都是RAM(SDRAM或者SRAM)中的地址。在这种情况下,程序没有运行初始化阶段加载的问题。从主机向

8、目标机载入程序的时候,程序映像文件中代码段(code或text)、只读数据段、读写数据段依次载入目标系统RAM(SDRAM或者SRAM)的空间中。程序载入到目标机之后,将从代码区的地址开始运行,在运行的初始化阶段,将开辟未初始化数据区,并将其初始化为0,在运行时将动态开辟堆区和栈区。在没有操作系统的情况下,开辟内存的工作都是由编译器生成的代码完成的,实现的原理是在映像文件中加入这些代码。主要工作包括:在程序运行时根据实际大小开辟未初始化的数据段;初始化栈区的指针,这个指针和物理内存的实际大小有关;在调用相关函数(malloc、free)时使用堆区,这些函数一般由调用库函数实现。表13-4列出了

9、C语言程序在RAM中的调试过程。表13-4C语言程序在RAM中的调试过程阶段涉及的部分主要工作程序的映像代码段(Code)只读数据段(ROData)读写数据段(RWData)将程序放置在RAM中初始化阶段未初始化数据段(BSS)开辟BSS段并且清零运行阶段代码段(Code)只读数据段(ROData)读写数据段(RWData)未初始化数据段(BSS)堆(heap)栈(stack)运行RAM代码段中的程序,动态地在RAM中开辟堆和栈知识点:程序直接载入RAM运行时,程序的加载位置和运行位置是一致的,因此不存在段复制的问题,需要在初始化阶段开辟未初始化区域,在运行时使用堆栈。13.4.2固化程序的X

10、IP运行固化应用是一种嵌入式系统常用的运行方式,其前提是目标代码位于目标系统ROM(Flash)中。ROM中的区域包括映像文件的代码段(code或text)、只读数据段(ROData)、读写数据段(RWData)。以XIP(在位置执行)方式运行程序时内存布局如图13-7所示。代码的运行也是在ROM(Flash)中,因此,在编译过程中代码的存储地址和运行地址是相同的,由于上电时需要启动,因此该代码的位置一般是(0x0)。在这种应用中,一件重要的事情就是将已初始化读写段的数据从Flash中复制到SDRAM中,由于已初始化读写段既需要固化,也需要在运行时修改,因此这一步是必须有的,在程序的初始化阶段

11、需要完成这一步。图13-7XIP运行程序时的内存布局一般来说,在编译过程中需要定义读写段和未初始化段的地址。在程序中可获取这些地址,然后就可以在程序的中加入复制的代码,实现读写段的转移。表13-5列出了C语言程序的XIP运行过程。表13-5C语言程序的XIP运行过程阶段涉及的部分主要工作程序的映像代码段(Code)只读数据段(ROData)读写数据段(RWData)程序放置在Flash中初始化阶段读写数据段(RWData)未初始化数据段(BSS)复制读写数据段到RAM中开辟未初始化段并且清零运行阶段代码段(Code)只读数据段(ROData)读写数据段(RWData)未初始化数据段(BSS)堆

12、(heap)栈(stack)运行Flash代码段中的程序,动态地在RAM中开辟堆和栈知识点:程序在ROM或者Flash中以XIP形式运行的时候,不需要复制代码段和只读数据段,但是需要在RAM中复制读写数据段,并另辟未初始化数据段。13.4.3固化程序的加载运行在某些时候,在存放程序的位置是不能运行程序的,例如程序存储在不能以XIP方式运行的Nand-Flash或者硬盘中,在这种情况下,必须将程序完全加载到RAM中才可以运行。固化程序加载运行的内存布局如图13-8所示:图13-8固化程序加载运行的内存布局依照这种方式运行程序,需要将Flash中所有的内容全部复制到SDRAM或者SRAM中。在一般

13、情况下,SDRAM或者SRAM的速度要快于Flash。这样做的另外一个好处是可以加快程序的运行速度。也就是说,即使Flash可以运行程序,将程序加载到RAM中运行也还有一定的优势。这样做也产生了另外一个问题:代码段的载入地址和运行地址是不相同的,载入地址是在ROM(Flash)中,但是运行的地址是在RAM(SDRAM或者SRAM)中。对于这个问题,不同的系统在加载程序的时候有不同的解决方式。C语言固化程序的加载运行过程如表13-6所示。表13-6C语言固化程序的加载运行时各段的情况阶段涉及的部分主要工作代码的映像代码段(Code)只读数据段(ROData)读写数据段(RWData)将程序放置在

14、Flash中初始化阶段代码段(Code)只读数据段(ROData)读写数据段(RWData)未初始化数据段(BSS)加载代码段和只读数据段到RAM中复制读写数据段到RAM中开辟未初始化段并且清零运行阶段代码段(Code)只读数据段(ROData)读写数据段(RWData)未初始化数据段(BSS)堆(heap)栈(stack)运行RAM代码段中的程序,动态地在RAM中开辟堆和栈知识点:固化程序在加载运行时,需要复制代码段、只读数据段和读写数据段到RAM中,并另辟未初始化数据段,然后在RAM中运行程序(执行代码段)。以这种加载方式的运行程序,另外一个重要的问题是:如何把代码移到RAM中。在有操作系

15、统的情况下,代码的复制工作是由操作系统完成的,在没有操作系统的情况下,处理方式相对复杂,程序需要自我复制。显然,这种方式实现的前提是代码最初放置在可以以XIP方式执行的内存中。程序本身复制的过程也是需要通过程序代码完成的,这时需要程序中的代码根据将包含自己的程序从ROM或者Flash中复制到RAM中。这是一个比较复杂的过程,程序的最前面部分是具有复制功能的代码。系统上电后,从ROM或者Flash起始地址运行,具有复制功能的代码将全部代码段和其他需要复制的部分复制到RAM中,然后跳转到RAM中重新运行程序。固化程序加载复制和跳转过程如图13-9所示。图13-9固化程序加载复制和跳转过程在代码的前

16、面一小部分是初始化的内容,这部分内容中有一部分是复制程序,这段复制程序将代码段复制至RAM中,当这段初始化程序运行完成后,将跳转到RAM中的某个地址运行。13.4.4C语言程序的运行总结在上面几节,主要介绍了C语言运行时内存的使用情况。其关注点是程序中主要的段,事实上,程序可能不仅包括了上述主要段,还可能包括一些头信息。程序实际的运行也分为在操作系统下运行和直接运行等情况。在具有操作系统的情况下,程序由操作系统加载运行,加载的时候可执行程序可以是一个文件,这个文件将包含程序的主要段以及头信息。对于Linux操作系统,目标程序是可执行的ELF(ExecutableandlinkingFormat

17、)格式;对于uCLinux操作系统,目标程序是Flat格式;对于需要在系统直接运行的程序,目标程序应该是纯粹的二进制代码,载入系统后,直接转到代码区地址执行。事实上,无论运行环境如何,C语言程序在运行时所进行的动作都是类似的。程序在准备开始运行的时候,以下几个条件都是必不可少的:1代码段必须位于可运行的存储区。2读写数据段必须在可以读写的内存中,而且必须经过初始化。3未初始化数据段必须在可以读写的内存中开辟,并被清空。对于第1点,代码段如果位于可以运行的存储区域中(例如NorFlash或者RAM),它就不需要加载,可以直接运行;如果代码段位于不能运行的存储区域中(例如:NandFlash或者硬盘)中,它就必须被加载到RAM运行。-

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁