文件管理,由于系统的内存有限并且不能长期保存,故平时总是把它们以文件的形式存放在外存中,需要时再将它们调入内存。如何高效的对文件进行管理是操作系统实现的目标。

1. 什么是内存

内存是用于存放数据的硬件。程序执行前需要先放到内存中才能被 CPU 处理。

思考: 在多道程序环境下,系统中会有多个程序并发执行,也就是说会有多个程序的数据需要同时放到内存中。那么,如何区分各个程序的数据是放在什么地方的呢?

[给内存的存储单元编地址]

2. 进程运行的基本原理

2.1. 指令的工作原理

写的代码要翻译成 CPU 能识别的指令。这些指令会告诉 CPU 应该去内存的哪个地址存/取数据,这个数据应该做什么样的处理。

上面指令中直接给出了变量 x 的实际存放地址(物理地址)。但实际在生成机器指令的时候并不知道该进程的数据会被放到什么位置。所以编译生成的指令中一般是使用逻辑地址(相对地址)

5

2.2. 逻辑地址&物理地址

宿舍四个人一起出去旅行,四个人的学号尾号分别是0、1、2、3。住酒店时酒店给你们安排了 4 个房号相连的房间。四个人按学号递增次序入住房间。比如 0、1、2、3 号同学分别入住了 5、6、7、8 号房间。

四个人的编号 0、1、2、3 其实是一个 “相对位置”,而各自入住的房间号是一个 “绝对位置” 只要知道 0 号同学住的是房号为 N 的房间,那么 M 号同学的房号一定是 N+M 。
也就是说,只要知道各个同学的 “相对位置” 和 “起始房号”,就一定可以算出所有同学的 “绝对位置”

指令中的地址也可以采用这种思想。编译时产生的指令只关心 “相对地址”,实际放入内存中时再想办法根据起始位置得到 “绝对地址”

编译时只需确定变量 x 存放的相对地址是 100(也就是说相对于进程在内存中的起始地址而言的地址)。CPU 想要找到 x 在内存中的实际存放位置,只需要用进程的起始地址 +100 即可。
相对地址又称逻辑地址,绝对地址又称物理地址。

2.3. 从写程序到程序运行

编译: 由编译程序将用户源代码编译成若干个目标模块(编译就是把高级语言翻译为机器语言)

链接: 由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块

装入(装载): 由装入程序将装入模块装入內存运行

3. 三种装入方式

装入模块装入内存时,需要对指令中的地址进行处理,装入的三种方式(用三种不同的方法完成逻辑地址到物理地址的转换):绝对装入、静态重定位和动态重定位

3.1. 绝对装入

在编译时,如果知道程序将放到内存中的哪个位置,编译程序将产生绝对地址的目标代码。装入程序按照装入模块中的地址,将程序和数据装入内存。

绝对装入只适合单道程序环境

3.2. 静态重定位

可重定位装入。编译、链接后的装入模块的地址都是从 0 开始的,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址。可根据内存的当前情况,将装入模块装入到内存的适当位置。装入时对地址进行“重定位”,将逻辑地址变换为物理地址(地址变换是在装入时一次完成的)

静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。作业一旦进入内存后,在运行期间就不能再移动,也不能再申请内存空间。

3.3. 动态重定位

动态重定位: 又称动态运行时装入。
编译、链接后的装入模块的地址都是从0开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,

把地址转换推迟到程序真正要执行时才进行。因此装入内存后所有的地址依然是逻辑地址。这种方式需要一个重定位寄存器的支持。

采用动态重定位时允许程序在内存中发生移动,并且可将程序分配到不连续的存储区中;在程序运行前只需装入它的部分代码即可投入运行,然后在程序运行期间,根据需要动态申请分配内存:便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间。

4. 三种链接方式

4.1. 静态链接

在程序运行之前,先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(装入模块),之后不再拆开。

4.2. 装入时动态链接

将各目标模块装入内存时,边装入边链接的链接方式。

4.3. 运行时动态链接

在程序执行中需要该目标模块时,才对它进行链接。其优点是便于修改和更新,便于实现对目标模块的共享。