|
汽车零部件采购、销售通信录 填写你的培训需求,我们帮你找 招募汽车专业培训老师
本文来源:C编译过程 以及 ELF文件(学习笔记) ,作者:嵌入一下?
一个用C语言编写的高级语言程序是从编写到打包、再到编译执行的基本过程,我们知道在CPU上执行的是低级别的机器语言,从高级语言到低级别的机器语言肯定是要经过翻译过程,这个过程大体的过程如下图所示:
在Unix系统中,从源文件到可执行目标文件是由编译驱动程序完成的,如大名鼎鼎的 gcc,翻译过程包括图中的四个阶段;1. 预处理阶段
预处理器(cpp)根据以字符#开头的命令修给原始的C程序,结果得到另一个C程序,通常以.i作为文件扩展名。主要是进行 文本替换、宏展开、删除注释 这类简单工作。
对应的命令:linux> gcc -E hello.c hello.i。
2. 编译阶段编译器将文本文件 hello.i 翻译成 hello.s ,包含相应的汇编语言程序。对应的命令:linux> gcc -S hello.c hello.s。
3. 汇编阶段将.s文件翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保存在目标文件.o中(把汇编语言翻译成机器语言的过程)。把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析;语法分析;语义检查和中间代码生成;代码优化;目标代码生成。主要是进行 词法分析 和 语法分析 ,又称为源程序分析,分析过程中发现有语法错误,给出提示信息。
词法分析阶段是编译过程的第一个阶段。这个阶段的任务是从左到右一个字符一个字符地读入源程序,即 对构成源程序的字符流进行扫描然后根据构词规则识别单词 (也称单词符号或符号)。词法分析程序实现这个任务。词法分析程序可以使用lex等工具自动生成。语法分析是编译过程的一个逻辑阶段。语法分析的任务是 在词法分析的基础上将单词序列组合成各类语法短语 ,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确.源程序的结构由上下文无关文法描述。语义分析是编译过程的一个逻辑阶段. 语义分析的任务是 对结构上正确的源程序进行上下文有关性质的审查 , 进行类型审查。例如一个C程序片断:
int arr[2], b; b = arr * 10; 源程序的结构是正确的。
语义分析将审查类型并报告错误: 不能在表达式中使用一个数组变量,赋值语句的右端和左端的类型不匹配。
在进行了语法分析和语义分析阶段的工作之后,有的编译程序将源程序变成一种内部表示形式,这种内部表示形式叫做中间语言或中间表示或中间代码。所谓“中间代码”是一种结构简单、含义明确的记号系统,这种记号系统复杂性介于源程序语言和机器语言之间,容易将它翻译成目标代码。另外,还可以在中间代码一级进行与机器无关的优化。想详细了解编译过程,请看:编译原理(douban.com)
3. 对应的命令:linux> gcc -c hello.c hello.o4. 链接阶段此时hello程序调用了printf函数。printf函数存在于一个名为printf.o的单独的预编译目标文件中。链接器(ld)就负责处理把这个文件并入到hello.o程序中,结果得到hello文件,一个可执行文件。最后可执行文件加载到储存器后由系统负责执行, 函数库一般分为静态库和动态库两种。
静态库是指 编译链接时,把库文件的代码全部加入到可执行文件中 ,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为.a。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是 在程序执行时由运行时链接文件加载库 ,这样可以节省系统的开销。动态库一般后缀名为.so,gcc在编译时默认使用动态库。
3. 想详细了解链接脚本,请看:链接脚本(Linker Scripts)语法和规则解析(自官方手册) - BSP-路人甲 - 博客园 (cnblogs.com)5. ELF文件
由上面的过程,我们可以看出在经过汇编器和连接器作用后都会输出一个目标文件,那这两个目标文件有什么样的区别呢?说到这里我们先引入目标文件的形式。
ELF(Executable Linkble Format)是一种Unix-like系统上的二进制文件格式标准。ELF标准中定义的采用 ELF 格式的文件分为4类:
ELF文件类型 | 说明 | 实例 | 可重定位文件(Relocatable File) | 内容包含了代码和数据,可以被链接成可执行文件或共享目标文件。 | Linux上的 .o 文件 | 可执行文件(Executable File) | 可以直接执行的程序 | Linux上的 a.out | 共享目标文件(Shared Object File) | 内容包含了代码和数据,可以作为链接器的输入,在链接阶段和其他的 Relocatable File 或者 Shared Object File 一起链接成新的 Object File;或者在运行阶段,作为动态连接器的输入,和Executable File 结合,作为进程的一部分来运行。 | Linux上的 .so | 核心转储文件(Core Dump File) | 进程意外终止时,系统可以将该进程的部分内容和终止时的状态信息保存到该文件中以供调试分析。 | Linux 上的 core 文件 | 6. 小结我觉得了解点C编译过程挺好的,对于软件开发的工程师来说,或多或少都会接触软件Build,也许只是参与深度的区别而已。恰逢个人最近花了不少时间在软件集成环境的配置上面,遇到了一些问题,也解决了一些问题,最终对于生成的一些文件有点好奇,比如ELF文件和MAP文件,所以搜索到了一篇分享C编译过程和ELF文件的深度好文,借此分享给有需要的朋友, 更多内容请关注下篇文章,下篇文章将对ELF文件进行详细解析。
创作不易,欢迎点赞再看收藏关注!
汽车研发交流群,有兴趣的朋友请添加群主:prOmiseyes,备注:公司+职务入群。仅限汽车从业人员。 |
|