我们编写的程序最初并不可以直接执行,是因为我们编写的程序是源代码,源代码所在文件就是源文件,源文件不可以直接运行是因为计算机只能识别二进制指令,所以源文件会经过两个步骤,就是编译和链接,最终生成可执行文件.exe,我们已知编译过程就是将源文件里的代码翻译成二进制文件最后生成目标文件,既然已经在编译阶段生成了二进制文件为什么还要链接,链接阶段是干什么的?
在软件开发中,“链接阶段”(Linking Stage)是编译过程的最后一个步骤,它将编译生成的目标文件(Object Files)和库文件(Library Files)合并,生成最终的可执行文件或库文件。链接阶段的主要任务包括符号解析和重定位。
一、链接阶段:
1. 符号解析(Symbol Resolution)
-
目标:确保所有符号(函数、变量等)都有明确的定义。
-
过程:
-
链接器会检查每个目标文件中未定义的符号(如调用的外部函数或引用的外部变量)。
-
在库文件或其他目标文件中查找这些符号的定义。
-
如果找不到符号的定义,链接器会报错(如
undefined reference
)。
-
符号解析就是扫描该文件是否有未定义的函数或变量,比如自定义函数function,function就是符号,而链接器会去其他目标文件找这个自定义函数的定义,如果未找到就会报错。如果是标准库的符号例如printf,其符号定义在库文件中。
2. 符号重定位(Symbol Relocation)
-
目标:将符号的引用与实际的地址关联起来。
-
过程:
-
每个目标文件中的代码和数据都有自己的局部地址空间。
-
链接器会将这些局部地址空间合并到一个全局地址空间中,并调整符号的地址。
-
例如,函数调用和变量引用的地址会被更新为最终的地址。
-
3. 合并代码和数据
-
目标:将多个目标文件中的代码和数据段合并到最终的可执行文件或库文件中。
-
过程:
-
链接器会将所有目标文件的代码段(如
.text
)合并到一起。 -
将数据段(如
.data
、.bss
)合并到一起。 -
生成最终的可执行文件或共享库。
-
4. 处理库文件
-
目标:将程序所需的库文件(静态库或动态库)链接到可执行文件中。
-
过程:
-
静态库:将静态库中的目标文件直接嵌入到可执行文件中。
-
动态库:在可执行文件中记录动态库的依赖关系,程序运行时再加载动态库。
-
5. 生成可执行文件
-
目标:生成最终的可执行文件或共享库。
-
过程:
-
链接器会根据操作系统的格式(如 ELF、PE)生成可执行文件。
-
可执行文件中包含程序的入口点(如
main
函数)、代码段、数据段等信息。
-
6. 处理重定位信息
-
目标:确保程序在加载到内存时能够正确运行。
-
过程:
-
链接器会生成重定位表(Relocation Table),记录需要调整的地址。
-
当程序加载到内存时,加载器会根据重定位表调整地址。
-
7. 优化(可选)
-
一些高级链接器会进行优化,如:
-
删除未使用的代码和数据(Dead Code Elimination)。
-
内联函数调用(Inline Expansion)。
-
合并重复的代码和数据。
-
总结
链接阶段的主要任务包括:
-
解析符号引用。
-
重定位符号地址。
-
合并代码和数据。
-
处理库文件。
-
生成可执行文件。
-
处理重定位信息。
链接阶段的最终目标是生成一个可以运行的程序或库文件。
二、链接库
1. 链接库的介绍
链接库(Link Library)通常指的是链接库文件。这些文件包含已编译的代码和数据,供程序在链接时使用。链接库主要有两种类型:
-
静态链接库(Static Library):
-
在编译时直接嵌入到最终的可执行文件中。
-
文件扩展名:Windows 上是
.lib
,Linux/Unix 上是.a
。 -
优点:程序独立,不依赖外部文件。
-
缺点:增加可执行文件大小,更新库需重新编译。
-
-
动态链接库(Dynamic Library):
-
在程序运行时加载,可被多个程序共享。
-
文件扩展名:Windows 上是
.dll
,Linux/Unix 上是.so
,macOS 上是.dylib
。 -
优点:节省内存和磁盘空间,更新库无需重新编译程序。
-
缺点:程序依赖外部文件,可能引发兼容性问题。
-
总结
链接库文件是包含编译代码的文件(库文件),供程序在链接或运行时使用,分为静态(静态库)和动态(动态库)两种类型。
链接库并不仅限于将标准库的函数链接到程序中,它涵盖的范围更广。
2. 链接库的作用
链接库的主要作用是提供预编译的代码(函数、类、数据等),供程序在编译或运行时使用。这些代码可以是:
-
标准库函数(如 C 标准库中的
printf
、malloc
等)。 -
第三方库函数(如 OpenSSL、Boost 等)。
-
自定义库函数(开发者自己编写的库)。
因此,链接库不仅仅是链接标准库的函数,还可以链接其他任何库。
2. 标准库 vs 链接库
-
标准库是语言或操作系统提供的一组核心库(如 C 标准库、C++ STL、Python 标准库等),通常包含常用的函数和工具。
-
链接库是一个更广泛的概念,包括标准库、第三方库和自定义库。
标准库通常是链接库的一部分,但链接库的范围更大。
3. 链接库的类型
链接库分为静态链接库和动态链接库:
-
静态链接库:在编译时将库的代码直接嵌入到可执行文件中。
-
动态链接库:在程序运行时加载库的代码。
无论是标准库还是第三方库,都可以通过静态或动态链接的方式使用。
4. 示例
-
标准库的链接:
当你使用 C 语言的printf
函数时,编译器会自动链接 C 标准库(如libc.a
或libc.so
)。 -
第三方库的链接:
如果你使用 OpenSSL 库中的函数,需要显式链接 OpenSSL 的库文件(如libssl.a
或libssl.so
)。 -
自定义库的链接:
如果你自己编写了一个库,也可以将其编译为静态库或动态库,并在其他程序中链接使用。
5. 总结
链接库不仅仅是链接标准库的函数,它还包括第三方库和自定义库。标准库只是链接库的一种特殊情况。链接库的作用是提供预编译的代码,供程序在编译或运行时使用。
说了这么多大概意思就是链接库是库文件,分为静态和动态,目标文件和链接库进行链接就是将目标文件和目标文件中的符号(函数或变量)定义(代码实现)所在的库文件进行链接。