目录
1 内存的连续分配
1.1 单一连续分配方式
1.2 固定分区分配
1.3 动态分区分配
2 内存的非连续分配
2.1 页式存储
2.1.1 基本概念
2.1.2 地址变换
2.1.3 分页管理方式存在的问题
2.1.4 具有快表的地址变换机构
2.1.5 二级页表
2.2 段式存储
2.2.1 基本概念
2.2.2 地址变换
2.2.3 段的共享
2.3 分页与分段的区别
2.4 段页式存储
2.4.1 基本概念
2.4.2 地址变换
3 虚拟内存
3.1 请求分页存储管理
3.1.1 地址变换
3.2 页面置换算法
3.3 页面抖动( 颠簸)
3.4 驻留集大小
3.5 调入页面的时机
3.6 从何处调入页面
内存在此方式下分为系统区和用户区
系统区仅提供给操作系统使用,通常在低地址部分
用户区是为用户提供的、除系统区之外的内存空间
优点:简单、无外部碎片,可以釆用覆盖技术,不需要额外的技术支持
缺点:只能用于单用户、单任务的操作系统中,有内部碎片,存储器的利用率极低
固定分区分配是最简单的一种多道程序存储管理方式。
将用户内存空间划分为若干个固定大小的区域,每个分区只装入一道作业。
当有空闲分区时,便可以再从外存的后备作业队列中,选择适当大小的作业装入该分区,如此循环。
划分分区方法:
存在的问题:
又称为可变分区分配,这种分区方法不预先将内存划分,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。因此系统中分区的大小和数目是可变的。
动态分区分配算法
首次适应(First Fit)算法:空闲分区以地址递增的次序链接。分配内存时顺序查找,找到大小能满足要求的第一个空闲分区。
最佳适应(Best Fit)算法:空闲分区按容量递增形成分区链,找到第一个能满足要求的空闲分区。
最坏适应(Worst Fit)算法:又称最大适应(Largest Fit)算法,空闲分区以容量递减的次序链接。找到第一个能满足要求的空闲分区,也就是挑选出最大的分区。
临近适应算法(Next fit)算法:从当前位置开始,搜索第一个能满足进程要求的内存空间
动态分区的缺点
随着时间的推移,内存中会产生越来越多的外部碎片,内存的利用率随之下降。
基本思想:用户程序的地址空间被划分成若干固定大小的区域,称为“页”,相应地,内存空间分成若干个物理块或页帧(Page Frame),页和块的大小相等。可将用户程序的任一页放在内存的任一块中,实现了离散分配:物理块不一定连续。每个页对应一个物理块。
逻辑地址结构:地址结构包含两部分:前一部分为页号P,后一部分为页内偏移量W。如果是32位地址,则0~11位为页内地址,即每页大小为4KB;12~31位为页号,地址空间最多允许有页
页表:因为程序数据存储在不同的页面中,而页面又离散的分布在内存中,因此需要一个页表来记录逻辑地址和实际存储地址之间的映射关系,以实现从页号到物理块号的映射
每个进程也以块为单位进行划分。每一个进程都拥有一个自己的页表,PCB表中有指针指向页表。
分页存储管理方式中,又根据运行作业时是否要把作业的所有页面都装入内存才能运行分为基本分页存储管理方式和请求分页存储管理方式。
地址变换的任务是将逻辑地址转换为内存中物理地址,地址变换是借助于页表实现的
基本地址变换机构当进程执行时,将页表始址和长度存入页表寄存器
设页大小为L(一般为4K),逻辑地址A到物理地址E的变换过程如下:
以上整个地址变换过程均是由硬件自动完成的
若页表全部放在内存中,则存取一个数据或一条指令至少要访问两次内存:
为提高地址变换速度,增设一个具有并行查询能力的特殊高速缓冲存储器,称为“联想存储器”或“快表”,存放当前访问的页表项。与此对应,主存中的页表也常称为慢表。
这样由逻辑地址的页号P直接在快表里查找:
理论依据:局部性原理
局部性原理:
时间上的局部性:最近被访问的页在不久的将来还会被访问
空间上的局部性:内存中被访问的页周围的页也很可能被访问
如果内存的逻辑地址很大,将会导致程序的页表项会很多,而页表在内存中是连续存放的,所以相应的就需要较大的连续内存空间。
为了解决这个问题,可以采用两级页表或者多级页表的方法:外层页表一次性调入内存且连续存放,内层页表离散存放。
所以一共需要访问内存3次才可以读取一次数据:访问顶级页表->访问二级页表->访问内存中的数据
分页是为了提高内存利用率,提升计算机的性能, 且分页通过硬件机制实现,对用户完全透明
而分段是为了满足程序员在编写代码的时候的一些逻辑需求(比如数据共享,数据保护,动态链接等)。
基本思想:将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息,每个段内部从0开始编址。存储分配时,以段为单位,每个段内部连续分配内存,段与段在内存中可以不相邻接,也实现了离散分配。例如,用户进程由主程序、两个子程序、栈和一段数据组成,于是可以把这个用户进程划分为5个段。
逻辑地址结构:段号S与段内偏移量W两部分组成。如果是32位地址,段号为16位,段内偏移量为16位,则一个作业最多可有=65536个段,最大段长为65536B即64KB
页式系统中,逻辑地址的页号和页内偏移量对用户是透明的,但在段式系统中,段号和段内偏移量必须由用户显示提供,在髙级程序设计语言中,这个工作由编译程序完成
段表:每个进程都有一张逻辑空间与内存空间映射的段表,其中每一个段表项对应进程的一个段。
访问内存的时候根据段号和段表项的长度计算当前访问段在段表中的位置,然后访问段表,得到该段的物理地址,根据该物理地址以及段内偏移量就可以得到需要访问的内存。
为了实现进程从逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器
段表寄存器存了段表始址F和段表长度M,从逻辑地址A到物理地址E之间的地址变换过程如下:
段的共享是通过两个作业的段表中相应表项指向被共享的段的同一个物理副本来实现的
不能修改的代码称为纯代码或可重入代码(它不属于临界资源),这样的代码和不能修改的数据是可以共享的
而可修改的代码和数据则不能共享
段式管理
页式管理
分页与分段的区别
页式存储管理能有效地提高内存利用率,而分段存储管理能反映程序的逻辑结构并有利于段的共享。
如果将这两种存储管理方法结合起来,就形成了段页式存储管理方式
基本思想:
逻辑地址结构:段号S、页号P和页内偏移量W。
每个进程建立一张段表,而每个分段有一张页表
为了实现进程从逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器
进行一次访问实际需要三次访问内存
虚拟内存的基本思想是:在程序装入时,可以将程序的一部分装入内存,而将其余部分留在外存,就可以启动程序执行。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。
虚拟内存容量:内存+外存
与传统存储器比较虚拟存储器有以下三个主要特征:
虚拟内存的实现有以下两种方式:
将当前需要的一部分页面装入内存,便可以启动作业运行。在作业执行过程中,当所要访问的页面不在内存时,再通过调页功能将其调入,同时还可以通过置换功能将暂时不用的页面换出到外存上,以便腾出内存空间
请求分页系统中的地址变换机构,是在分页系统地址变换机构的基础上,为实现虚拟内存,又增加了某些功能而形成的
请求分页系统中,每当所要访问的页面不在内存时,便产生一个缺页中断,请求操作系统将所缺的页调入内存
缺页中断处理中:
进程运行时,若其访问的页面不在内存而需将其调入,但内存已无空闲空间时,就需要从内存中调出一页程序或数据,送入磁盘的对换区。
选择调出页面的算法就称为页面置换算法
最理想的状态下,所选择的被淘汰页面将是最长时间内不再被访问的页面,当然,这样的算法不可能实现,因为不确定一个页面在何时会被用到。
这种算法的思想和队列是一样的,该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予淘汰。
实现简单,把一个进程已调入内存的页面按先后次序链接成一个队列,并且设置一个指针总是指向最老的页面。
缺点:对于有些经常被访问的页面如含有全局变量、常用函数、例程等的页面,不能保证这些不被淘汰。
根据页面调入内存后的使用情况做出决策。LRU置换算法是选择最近最久未使用的页面进行淘汰。
实现:
1.为每个页面设置一个访问字段,来记录页面自上次被访问以来所经历的时间,淘汰页面时选择现有页面中值最大的予以淘汰
2.利用一个特殊的栈保存当前使用的各个页面的页面号。每当进程访问某页面时,便将该页面的页面号从栈中移出,将它压入栈顶。因此,栈顶永远是最新被访问的页面号,栈底是最近最久未被访问的页面号。
把所有的页面都保存在一个类似钟面的环形结构中
每一个页面增加一个使用位
颠簸本质上是指频繁的页面调度行为,具体来讲,进程发生缺页中断,这时,必须置换某一页。然而,其他所有的页都在使用,它置换一个页,但又立刻再次需要这个页。因此,会不断产生缺页中断,导致整个系统的效率急剧下降,这种现象称为颠簸(抖动)
内存颠簸的解决策略包括:
如果是因为页面替换策略失误,可以修改替换算法来解决这个问题;
如果是因为运行的程序太多,造成程序无法同时将所有频繁访问的页面调入内存,则要降低多道程序的数量;
终止该进程或增加物理内存容量。
驻留集:对于分页式的虚拟内存,不需要把一个进程的所有页都读取到主存,操作系统必须决定读取多少页。也就是说,给特定的进程分配多大的主存空间,这就是驻留集。
主要考虑以下几点:
操作系统通常釆用三种策略:
为每个进程分配一定数目的物理块,在整个运行期间都不改变。若进程在运行中发生缺页,则只能从该进程在内存中的页面中选出一页换出,然后再调入需要的页面
为系统中的每个进程分配一定数目的物理块,操作系统自身也保持一个空闲物理块队列。
当某进程发生缺页时,系统从空闲物理块队列中取出一个物理块分配给该进程,并将欲调入的页装入其中。
为每个进程分配一定数目的物理块
当某进程发生缺页时,只允许从该进程在内存的页面中选出一页换出,这样就不会影响其他进程的运行
如果进程在运行中频繁地缺页,系统再为该进程分配若干物理块,直至该进程缺页率趋于适当程度
反之,若进程在运行中缺页率特别低,则可适当减少分配给该进程的物理块
为确定系统将进程运行时所缺的页面调入内存的时机,可釆取以下两种调页策略
根据局部性原理,一次调入若干个相邻的页可能会比一次调入一页更高效。但如果调入的一批页面中大多数都未被访问,则又是低效的。所以就需要釆用以预测为基础的预调页策略,将预计在不久之后便会被访问的页面预先调入内存
进程在运行中需要访问的页面不在内存而提出请求,由系统将所需页面调入内存。
由这种策略调入的页一定会被访问,且这种策略比较易于实现,故在目前的虚拟存储器中大多釆用此策略。
缺点在于每次只调入一页,调入调出页面数多时会花费过多的I/O开销
请求分页系统中的外存分为两部分:
故对换区的磁盘I/O速度比文件区的更快,这样从何处调入页面有三种情况:
可以全部从对换区调入所需页面,以提髙调页速度。为此,在进程运行前,需将与该进程有关的文件从文件区复制到对换区
凡不会被修改的文件都直接从文件区调入,而当换出这些页面时,由于它们未被修改而不必再将它们换出。
对于那些可能被修改的部分,在将它们换出时须调到对换区,以后需要时再从对换区调入。
与进程有关的文件都放在文件区,故未运行过的页面,都应从文件区调入
曾经运行过但又被换出的页面,由于是被放在对换区,因此下次调入时应从对换区调入
进程请求的共享页面若被其他进程调入内存,则无需再从对换区调入