内存是用于存储数据的硬件。程序执行前需要先放到内存中才能被CPU处理。代码编译到运行流程:编译->链接->装入。
编译:代码会被编译成机器码被操纵系统执行,包含相应指令、操作码、和若干参数等。由编译程序Compiler将源代码编译成若干个目标模块,翻译成机器语言。在生成机器指令时并不知道该进程的数据会被放到什么位置,所以编译时生成的指令中一般是使用逻辑地址。
链接:由链接程序Linker将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块(可执行文件)。有三种链接方式:
1.静态链接:在程序运行前,先将各个目标模块以及他们所需的库函数连接成一个完成的可执行文件,之后不再拆开;
2.装入时动态链接:将各目标模块装入内存时,边装入边链接。
3.运行时动态链接:在程序执行中需要该目标模块时,才对它进行链接。优点是便于修改和更新,便于实现对目标的共享。->dll
装入:可执行文件只有被装载到内存以后才能被CPU执行,由装入程序Loader将装入模块装入内存运行. 有三种装入方式:
1.绝对装入:在编译时,如果知道程序将放到内存中的哪个位置,编译程序将产生绝对地址的目标代码。即编译、链接后得到的装入模块的指令直接就使用了绝对地址;装入程序按照装入模块中的地址,将程序和数据装入内存;绝对装入只适用于单道程序环境。
2.静态重定位(可重定位装入):编译、链接后的装入模块的地址都是从0开始的,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址,装入程序根据内存的当前情况,将装入模块装入到内存的适当位置,并在装入时对地址进行重定位,将逻辑地址变换为物理地址。地址变换是在装入时一次性完成的。
特点:静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,则装入失败。作业一旦进入内存后,运行期间不能再移动,也不能再申请新的内存空间。
3.动态重定位(动态运行时装入):编译、链接后的装入模块的地址都是从0开始的,装入程序把装入模块装入内存后,在程序真正执行时候进行地址转换。因此装入内后后所有地址依然是逻辑地址。这种方式需要一个重定位寄存器(存放装入模块存放的起始位置)的支持。采用动态重定位时允许程序在内存中发生移动。
特点:并且可将程序分配到不连续的内存空间中;还可以只用装入部分程序代码即可运行,在程序运行时进行动态内存分配即可;便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间;
简单的编译、链接、装入的示意图