CSAPP中关于链接(linker)部分的笔记
1. Object file
Object file是一些程序指令、数据结构和数据所组成的集合,由三种形式,分别为Relocatable object file, Executable object file 和 Shared object file。
- Relocatable object file - Contains binary code and data in a form that can be combined with other relocatable object files at compile time to create an executable object file.
- Executable object file - Contains binary code and data in a form that can be copied directly into memory and executed.
- object file - A special type of relocatable object file that can be loaded into memory and linked dynamically, at either load time or run time.
在Linux与Unix中把这种数据格式称为Executable and Linkable Format, 简称为ELF, 格式为
2. 静态链接库
根据上面的那个编译流程图可知,在生成可执行文件的时候需要把多个Relocatble object file
链接在一起,我们在写程序的时候经常会用到一些通用程序库,如何把他们链接在一起呢?一个方法是把所有的库文件都生成一个.o
文件,然后编译的时候传给链接器,但是这个会导致程序变得非常大,并且当程序运行的时候需要载入内存,也会造成内存空间的浪费。那如果我们把库中的每个代码文件分开生成.o
文件,然后当写的代码需要那一部分代码就引入那个.o
文件,这样如果代码复杂最后需要传入的文件太多了,比较麻烦。所以此时就提出了静态链接库的概念,可以首先将每个代码文件生成一个.o
文件,再将这些相似的文件合并成一个.a
文件,这个.a
文件就是静态链接库。下面创建一个vector
库,实现两个数组对应元素的相加与相乘功能,首先编写数组对应元素相加与相乘的函数,分别命名为addvec.c
和multvec.c
,函数内容如下
addvec.c
void addvec(int *x, int *y, int *z, int n){ int i; ++; addcntfor(i = 0; i < n; i++){ [i] = x[i] + y[i]; z} }
multvec.c
.a addvec.o multvec.ovoid multvec(int *x, int *y, int *z, int n){ ar libvectorint i; ++; multcntfor(i = 0; i < n; i++){ [i] = x[i] * y[i]; z}ar libvector.a addvec.o multvec.o }
然后再写一个头文件包含这两个库的函数原型, 命名为vector.h
void addvec(int *x, int *y, int *z, int n);
void multvec(int *x, int *y, int *z, int n);
现在开始将这些文件编译成一个静态库,首先将addvec.c
和multvec.c
编译但不链接,也就是生成.o
文件
gcc -c addvec.c multvec.c
这里-c
参数就表示只编译,但是不打包,这样就会生成addvec.o
和multvec.o
这两个relocation object file
,然后可以将这两个文件合并成一个静态库
ar rcs libvector.a addvec.o multvec.o
生成的libvector.a
就是我们需要的静态库,下面可以写一个main.c
来调用刚才生成的静态库
#include<stdio.h>
#include "vector.h"
int x[2] = {1, 2};
int y[2] = {3, 4};
int z[2];
int main(){
(x, y, z, 2);
addvec("z = [%d %d]\n", z[0], z[1]);
printfreturn 0;
}
首先需要将main.c
编译成main.o
的relocation object file
, 然后再使用静态链接,将静态库和main.o
链接再一起,命令如下
gcc -c main.c
gcc -static -o a.out main.o -L. -lvector
3. 动态链接库
静态库虽然有很多优先但是也有它的缺陷,比如当使用静态库的时候,如果库中的代码发生更改,那么所有需要该库的项目都需要重新编译,又比如需要项目都用到了一些基础库,比如输入,当这些项目运行起来之后,这些库会被重复载入内存,浪费内存空间。为了解决这些问题,就提出了动态链接库,动态链接库的定义为: Ashared library is an object module that, at either run time or load time, can be loaded at an arbitrary memory address and linked with a program in memory. 如何来创建并引入动态库可以参考这篇文章 shared-libraries-linux-gcc