0%

Linux环境下程序的链接,装载和库

Linux环境下编译过程总体概览

GCC整个编译过程可分为这几个步骤:预处理、编译、汇编、链接

预编译

预编译过程主要是处理源代码文件中那些以#开头的预编译指令,具体来说

  • 处理#define, 将所有的宏定义#define展开
  • 处理#if, #else, #endif等等条件编译指令
  • 处理#include, 原地插入文件(有时候你可以看到很有意思的头文件包含)
  • 删除注释

可以使用以下命令来调用预编译器

  • gcc -E HelloWorld.c -o HelloWorld.i

  • cpp HelloWorld.c > HelloWorld.i

编译

编译过程是最核心也是最复杂的过程, 复杂性从GCC的编译选项中就可以略知一二,它主要是对预编译完的文件进行词法,语法,语义分析并进行优化,最终产生对应的汇编代码文件。

可以使用以下命令来调用编译器

  • gcc -S HelloWorld.i -o HelloWorld.s

汇编

汇编器把汇编代码转换成目标文件,比较单纯。

可以使用以下命令来调用汇编器

  • as HelloWorld.s -o HelloWorld.o

链接

链接器最终将多个目标文件链接起来形成可执行文件

为什么需要链接?
简单来说因为每个源代码模块都独立地进行编译,链接就是要处理各个模块之间的相互引用,使他们之间能够互相衔接。比如说我们的HelloWorld.c中的main函数并不知道printf这个函数的地址,链接器在链接的时候会根据引用到的符号printf,自动去相应的模块查找printf的地址,然后将HelloWorld.c模块中引用到printf的指令进行重新修正,让它的目标地址成为真正的printf函数的地址,这个就是链接的基本过程。

求大佬赏个饭