操作系统存储器管理相关知识总结
一、存储器的层次结构
如图为存储器层次结构示意图,由上到下,每“位”的价格递减、容量递增、存取时间递增、处理器访问存储器的频率递减。
1、计算机体系结构
计算机系统包括CPU、内存、I/O设备、总线等。
这里要注意CPU里面有寄存器和高速缓存,因为之前学计算机组成原理学的不好,所以这一点之前并不知道,还以为寄存器和高速缓存都在内存里面。
2、内存层次
在CPU内有两级缓存,当CPU在读写数据时,如果数据已经存在于高速缓存中,则CPU可以直接使用缓存中的数据,此时的访问速度是最快的,我们在写程序的时候是感觉不到缓存的存在的,因为这部分完全由硬件来做控制。但如果缓存中没有数据,CPU就要从内存中查询数据,而内存的访问就需要使用操作系统了。如果内存中仍然找不到数据,就需要从外存中查找数据了。从上到下这些访问速度的差异有很大。
3、操作系统的内存管理
在研究与内存管理相关的各种机制和策略时,清楚内存管理要满足的需求非常有用。内存管理的需求主要有以下几个方面:
1、重定位
重定位就是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程。它是实现多道程序在内存中同时运行的基础。重定位有两种,分别是动态重定位与静态重定位。
2、保护
每个进程都应受到保护,以免被其他进程有意无意的干扰
3、共享
任何保护机制都必须具有一定的灵活性,以允许多个进程访问内存的同一部分。
4、逻辑组织
5、物理组织
二、程序的处理
在多道程序环境下,要使程序运行,必须先为之创建进程。而创建进程的第一件事,便是将程序和数据装入内存。如何将一个用户源程序变为一个可在内存中执行的程序,通常都要经过以下几个步骤:即编译、链接、加载。
1、编译
由编译程序将用户源代码编译成CPU可执行的目标代码。形成的目标代码,每个代码都是以0为基址顺序进行编址。原来用符号名访问的单元用具体的数据–单元号来取代。这样生成的目标程序占据一定的地址空间,称为作业的逻辑地址空间,简称逻辑地址空间。
2、链接
由链接程序(Linker)将编译后形成的一组目标模块(程序段),以及它们所需要的库函数链接在一起,形成一个完整的装入模块(加载模块)(Load Module);链接器的功能是把一组目标模块作为输入,产生一个包含完整程序和数据模块的加载模块,并传递给加载器。
链接的方式主要有三种:静态链接、装入时动态链接、运行时动态链接。
静态链接是由 链接器在链接时将库的内容加入到可执行程序中的做法。 链接器是一个独立程序,将一个或多个库或目标文件(先前由 编译器或 汇编器生成)链接到一块生成可执行程序。静态链接的最大缺点是生成的 可执行文件太大,需要更多的 系统资源,在装入内存时也会消耗更多的时间。
装入时动态链接分为如下步骤,待加载的加载模块读入内存,应用模块中到一个外部模块(目标模块)的任何引用都会导致加载程序查找目标模块,加载他。并把这些引用修改为相对于应用程序模块开始处的相对地址。
使用运行时动态链接时,某些链接工作被推迟到执行时,这样一些对目标模块的外部引用保留在被加载的程序中,当调用的模块不存在时,操作系用定位该模块,加载它,并把它链接到调用模块中。这些模块一般是共享的。在Windows 环境下,这些模块称为动态链接库。
3、加载(装入)
加载的方式一般有三种:绝对加载(绝对装入)、可重定位加载(可重定位装入)、动态运行时加载(动态运行时装入)
绝对加载 绝对加载器要求给定加载模块总被加载到内存中的同一位置。因此,在提供给加载 器的加载模块中,所有的地址访问必须是确定的,或者说是绝对的内存地址。例如,若图7.14中的 x是1024位置,则加载模块中的第一个字在内存中的地址为1024。
可重定位加载 在加载之前就把内存访问绑定到具体的地址的缺点是,会使得加载模块只能放 置到内存中的一个区域。但是,当多个程序共享内存时,不可能事先确定哪块区域用于加载哪个特 定的模块,最好是在加载时确定。因此,需要一个可分配到内存中任何地方的加载模块。
为满足这个新需求,汇编器或编译器不产生实际的内存地址(绝对地址),而是使用相对于某些 已知点的地址,如相对于程序的起点。这种技术如图7.15©所示。加载模块的起点指定为相对地址0, 模块中的所有其他内存访问都用与该模块起点的相对值来表示。
动态运行时加载 可重定位加载器非常普遍,且相对于绝对加载器具有明显的优点。但是,在 多道程序设计环境中,即使不依赖于虚存,可重定位的加载方案仍是不够的。由于需要把进程换入 或换出内存来增大处理器的利用率,而为最大限度地利用内存,又希望能在不同的时刻把一个进程 映像换回到不同的位置,因此,程序被加载后,可能被换岀到磁盘,然后又被换回到内存中不同的 位置。若在开始加载时,内存访问就被绑定到绝对地址,则前面提到的情况将是不可能实现的。
一种替代方案是在运行时真正在使用某个绝对地址时再计算它。为达到这一目的,加载模块被 加载到内存中时,其所有内存访问都以相对形式表示,如图7.15(d)所示,一条指令只有在真正被执 行时才计算其绝对地址。为确保该功能不会降低性能,这些工作必须由特殊的处理器硬件完成,而不用软件实现。
三、内存分配
1、连续内存分配
内存管理的主要操作是处理器把程序装入内存中执行。在几乎所有的现代多道程序设计系统 中,内存管理涉及一种称为虚存(虚拟内存)的复杂方案。虚存基于分段和分页这两种基本技术, 或基于这两种技术中的一种。在考虑虚存技术之前,先考虑一些不涉及虚存的简单技术(表7.2总 结了本章和下一章中分析的全部技术),其中分区技术曾用在许多己过时的操作系统中。另外两种技 术,即简单分页和简单分段,实际中并未使用过。在不考虑虚存的前提下,先分析这两种技术有助 于阐明虚存的概念。
碎片的概念
我们一般将碎片分为两种,一种是内部碎片、一种是外部碎片。
内部碎片 分配单元内部的未被使用的内存,取决于分配单元的大小是否要取整。
外部碎片 分配单元之间的未被使用内存。
单一连续分配
这是一种最简单的存储管理方式,在早期的单道批处理系统的小型机中常使用这种管理方案。采用这种管理方案时,内存被分成两个区域,一个是系统区域,仅供操作系统使用,通常设置在内存的低端;另一个是用户区,它是除系统区以外的全部内存区域,这部分区域是提供给用户使用的区域,任何时刻主存储器中最多只有一个作业。所以,单一连续区存储管理只适用于单用户的情况。
固定分区分配
大多数内存管理方案都假定操作系统占据内存中的某些固定部分,而内存中的其余部分则供多 个用户进程使用。管理用户内存空间的最简方案就是对它分区,以形成若干边界固定的区域。
动态分区分配
对于动态分区而言,分区长度和数量是可变的。当进程装入内存时,系统会给它分配一块与其所需容量完全相等的内存空间。
动态分区方法最初不错,但它最终在内存中形成了许多小空洞。随着时间 的推移,内存中形成了越来越多的碎片,内存的利用率随之下降。
伙伴系统
图7.6给出了一个初始大小为1MB的块的例子。第一个请求A为100KB,需要一个128KB的 块。最初的块被划分成两个512KB大小的伙伴,第一个伙伴又被划分成两个256KB大小的伙伴, 其中的第一个又划分成两个128KB大小的伙伴,这两个128KB的伙伴中的一个分配给A。下一个 请求B需要256KB的块,因为已有这样的一个块,随即分配给它。在需要时,继续进行这样的分裂 和合并过程。注意当E被释放时,两个128KB的伙伴合并为-个256KB的块,这个256KB的块又 立即与其伙伴合并成一个512KB的块。
动态重定位分区分配
2、非连续内存分配
段式存储管理
页式存储管理
页表
缓存对应块表
间接访问对应多级页表
快表和多级页表
段页式存储管理
将段式和页式结合在一起,大的分段内部还有分页。
反置页表
反置页表和页寄存器的区别是它把进程ID也考虑进来了。