通常我们使用gcc来生成可执行程序,命令为:gcc hello.c,默认生成可执行文件a.out
其实编译(包括链接)的命令:gcc hello.c 可分解为如下4个大的步骤:
- 预处理(Preprocessing)
- 编译(Compilation)
- 汇编(Assembly)
- 链接(Linking)
程序装载
程序执行的过程是 编译-汇编-链接成可执行文件–通过装载器把可以执行文件装载到内存中,cpu从内存中读取装载器装入的指令和数据。
装载器把指令和数据装载到内存需要满足两个要求:
- 可执行程序加载后占用的内存空间是连续的。执行指令的时候是一条一条指令的执行
- 不能让程序自身决定他在内存中加载的位置,因为如果有很多程序执行的话,那么程序本身不知道那个内存地址是否已经被占用了。
为了满足这些条件(因为有的程序想要实现上面的功能,那系统就假装能让他们实现),系统用了一个办法,在物理地址空间中找到了一块连续的内存,分配给程序,然后把这段物理地址和程序里需要的地址做一个映射。 这就是虚拟地址空间和物理地址空间
链接
当系统启动时,可能有非常多的程序需要通过装载器把数据和代码装载到内存中,而且又很多程序会用到相同的数据和代码,如果每次都装载那非常消耗内存。因此就需要用链接的方式来达到代码的复用。
通过调用链接器ld来链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件。
ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了文件的路径名)。
链接分为静态链接和动态链接。
静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。
而动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。
网友评论