- 分配:进程装入主存时,存储管理软件进行具体的主存分配操作,并设置一个表格记录主存空间的分配情况
- 去配:当某个进程撤离或主动归还主存资源时,存储管理软件要收回它所占用的全部或者部分存储空间,调整主存分配表信息
- 多个进程共享主存储器资源:多道程序设计技术使若干个程序同时进入主存储器,各自占用一定数量的存储空间,共同使用一个主存储器
- 多个进程共享主存储器的某些区域:若干个协作进程有共同的主存程序块或者主存数据块
- 按照分区复用:主存划分为多个固定/可变尺寸的分区,一个程序/程序段占用一个分区
- 按照页架复用:主存划分成多个固定大小的页架,一个程序/程序段占用多个页架
- 绝对装载
- 可重定位装载
- 动态运行时装载
- 静态地址重定位:由装载程序实现装载代码模块的加载和地址转换(无需硬件支持),把它装入分配给进程的内存指定区域,其中所有指令代码和数据的逻辑地址在执行前一次全部修改为内存物理地址。早期单任务单用户OS使用。
- 动态地址重地位:由装载程序实现装载代码模块的加载,把它装入进程的内存在指定区域,但对链接程序处理过的应用程序逻辑地址不做修改,程序内存起始地址被置入重定位寄存器(基址寄存器)。程序执行过程中每当CPU访问程序和数据引用内存地址时,由硬件地址转换机构截取此逻辑地址并加上重定位寄存器的值。
- 运行时链接地址重定位
- 数据段可指定R/W或RO;程序段可指定R/E或RO
- 私有主存区中的信息可读可写;公共区中的共享信息则需根据授权
- 非本进程信息、未获授权的信息(如OS内核、页表等)不可读写
- 访问越权(访问操作与所拥有的访问权限不符):页表中设定访问(存取)权限
- 地址越界(转换得到的物理地址不属于可访问范围)
- 支持至少2种运行模式
- 使一部分CPU状态只能由内核程序用管态指令(特权指令)读写而不能由用户程序读写:User/SuperVisor模式位、页表首地址、TLB等。
- 提供让CPU在管理模式和用户模式相互转换的机制:异常和陷阱(系统调用)使CPU从用户态转到内核态;异常处理中的“返回”指令使CPU从内核态转到用户态。
![](https://i-blog.csdnimg.cn/blog_migrate/34965db6aa73632c437f3f6d702236af.png)
- 移动技术:把已在内存中的进程分区连接到一起,也叫内存紧凑。
- 对换技术:如果当前一个或多个驻留进程都处于阻塞态,将其暂时移出内存(通常换出时间片耗尽或优先级较低的进程),腾出空间
- 覆盖技术:程序执行过程中不同的模块在内存中相互替代,以达到小内存执行大程序的目的。
- 虚拟存储器:在具有层次结构存储器的计算机系统中,自动实现部分装入和部分替换功能,从逻辑上为用户提供一个比物理内存大得多的、可寻址的虚拟存储器。
![](https://i-blog.csdnimg.cn/blog_migrate/bbad249427bd98abc808429875b52a49.png)
- 页大小(2KB~64KB)比Cache中的Block大得多,采用全相联映射:因为缺页时需要访问磁盘(约几百万个时钟周期),而cache缺失时访问主存仅需几十到几百个时钟周期,开销比Cache缺失开销大的多。因此,页命中率比cache命中率更重要!“大页面”和“全相联”可提高页命中率。
- 通过软件来处理“缺页”:缺页时需要访问磁盘,慢,不能用硬件实现。
- 采用Write Back写策略:避免频繁的慢速磁盘访问操作。
- 地址转换用硬件实现:加快指令执行
存储管理是OS管理主存储器的软件部分
-
为获得更好的处理性能,部分主存程序与数据(特别是关键性能数据)被调入Cache,存储管理需要对其进行管理,甚至包括对联想存储器的管理
-
为获得更大的虚拟地址空间,存储管理需要对存放在硬盘、固态硬盘、甚至网络硬盘上的虚拟存储器文件进行管理
存储管理的基本模式可分为:
-
单连续存储管理:一维逻辑地址空间的程序占用一个主存固定分区或可变分区
-
段式存储管理:段式二维逻辑地址空间的程序占用多个主存可变分区
-
页式存储管理:一维逻辑地址空间的程序占用多个主存页架区
-
段页式存储管理:段式二维逻辑地址空间的程序占用多个主存页架区
单连续存储管理
每个进程占用一个物理上完全连续的存储空间(区域)
-
单用户连续存储管理
主存区域划分为系统区与用户区。设置一个栅栏寄存器界分两个区域,硬件用它在执行时进行存储保护。
一般采用静态重定位进行地址转换。
硬件实现代价低,适用于单用户单任务操作系统,如DOS。
-
固定分区存储管理
支持多个分区,分区数量固定、大小固定。
可用静态/动态重定位。
存储保护一定是由硬件来做。
硬件实现代价低,一般为早期OS采用。
根据主存分配表进行主存分配与去配
硬件实现机制与动态重定位如图:
-
可变分区存储管理
固定分区存储管理不够灵活,既不适应大尺寸程序,又存在内存内零头,有浪费。
按照进程实际内存需求动态划分分区,创建一个进程时,根据进程所需主存量查看主存中是否有足够的空闲空间,若有,则按需要量分割一个分区;若无,则令该进程等待主存资源。由于分区大小按照进程实际需要量来确定,因此分区个数是随机可变的。
但可变分区方式也会随着进程的内存分配产生一些小的不可用的内存分区,称为内存外零头。
根据已分配区表和未分配区表进行主存分配与去配。由于分区数量动态调整,起址也是动态可变的,因此两张表一定链接成链表。
硬件实现机制与动态重定位如图:
可变分区方式的内存分配可算法有:
-
最先适应(first fit)分配算法:空闲区表按照内存起址先后组织成链表,总是在最前面找一个足够的分区予以分配
-
邻近适应(next fit)分配算法:把空闲区表组织成循环的队列进行分配
-
最优适应(best fit)分配算法:按照分区大小组织成队列,找一个最小的能够容纳该进程的分区予以分配。最容易产生外零头。
-
最坏适应(worst fit)分配算法
-
快速适应(quick fit)分配算法:该算法为那些经常用到的长度的空闲区设立单独的空闲区链表。此算法查找十分快速,只要按照进程长度直接搜索能容纳它的最小空闲区链表并取第一块分配,但归还内存空间时与相邻空闲区的合并复杂费时,而且存在一定空间浪费。
前四个为顺序搜索法,快速适应算法又称为分类搜索算法。
任何适配算法都不能避免产生外零头,可以采用移动技术(程序浮动技术)移动分区以解决内存外零头(需要动态重定位支撑)。
页式存储管理
分页存储器将主存划分成多个大小相等的页架,受页架尺寸限制,程序的逻辑地址也自然分成页。不同的页可以放在不同页架(不需要连续)中。
页式存储管理的逻辑地址由两部分组成,逻辑地址形式为页号:单元号
页式存储管理的物理地址也由两部分组成:形式为页架号:单元号
地址转换可以通过查页表完成。
管理空闲主存空间:可用一张位示图来记录主存分配情况。为每一个页架建立一个位来记载是否被占用(不需要记载被哪个进程占用);并记录主存剩余的空闲块数。
页式存储管理能够实现多个进程共享程序和数据
-
数据共享:不同进程可以使用不同页号共享数据页
-
程序共享:不同进程必须使用相同页号共享代码页,共享代码页中的JMP <页内地址>指令,使用不同页号做不到
页表放在主存,每次地址转换必须访问多次主存,先按页号读出页表中的相应页架号,再按计算出来的绝对地址进行读写,降低了存取速度。因此可以利用Cache存放部分页表。设置一个专用的高速存储器,用来存放TLB/快表,这种高速存储器是联想存储器,即按照内容寻址,而非按照地址访问。
TLB全相联时,TLB中的页表项没有index,只有Tag,页号需与每个Tag比较;
TLB组相联时,则页号高位为Tag,低位为index,用作组索引。
基于快表的地址转换流程为:
-
按逻辑地址中的页号查快表
-
若该页已在快表中,则由页架号和单元号形成绝对地址
-
若该页不在快表中,则再查主存页表形成绝对地址,同时将该页登记到快表中
-
当快表填满后,又要登记新页时,则需在快表中按一定策略淘汰一个旧登记项
多道程序环境下需要有进程表登记每个进程的页表。
每个进程有一个页表用于维系进程的主存完整性。进程占有处理器运行时,其页表起始地址和页表长度送入页表控制寄存器。
页式虚拟存储管理:把进程全部页面装入虚拟存储器,执行时先把部分页面装入实际内存,然后,根据执行行为,动态调入不在主存的页,同时进行必要的页面调出,是现代OS的主流存储管理技术。
首次只把进程第一页信息装入主存,称为请求页式存储管理
需要扩产页表项,其中有装入位、修改(Dirt)位、替换控制位、访问权限位、禁止缓存位、页架号。
一个页表的项数=虚拟地址空间大小/页大小。
(1)未分配页:进程的虚拟地址空间中“空洞”对应的页(如VP0、VP4)
(2)已分配的缓存页:有内容对应的已装入主存的页(如VP1、VP2、VP5等)
(3)已分配的未缓存页:有内容对应但未装入主存的页(如VP3、VP6)
-
CPU处理地址,若页驻留,则获得块号形成绝对地址;
-
当装入位V=0时,页不在内存发生缺页,则CPU发出缺页中断,当前进程被挂起。缺少的页从磁盘读到内存,若内存没有空间,则还要从内存选择一页替换到磁盘上,更新页表与快表,处理结束回到原指令继续执行。替换算法类似于Cache,采用回写法,淘汰时,根据dirty位确定是否要写回磁盘。
-
当读写操作不符合存取权限(Access Right)时,发生保护违例或访问违例:在屏幕上显示“内存保护错”或“访问违例”信息;当前指令的执行被阻塞,当前进程被终止
缺页中断的处理流程如图:
当主存空间已满而又需要装入新页时,页式虚拟存储管理必须按照一定的算法把已在主存的一些页调出去。选择淘汰页的工作称为页面调度 ,选择淘汰页的算法称为页面调度算法,页面调度算法设计不当,会出现刚被淘汰的页面立即又要调入,并如此反复,这种现象称为抖动或颠簸。
- 最佳页面替换算法(OPT):理想的调度算法,只可模拟,不可实现。当要调入新页面时,首先淘汰以后不再访问的页,然后选择距现在最长时间后再访问的页。
- 先进先出页面调度算法(FIFO):总是淘汰最先调入主存的那一页,或者说主存驻留时间最长的那一页(常驻的除外)。模拟的是程序执行的顺序性,有一定合理性。会出现Belady现象(如果对—个进程未分配它所要求的全部页面,有时就会出现分配的页面数增多但缺页率反而提高)
- 最近最少用页面调度算法(LRU):淘汰最近一段时间内最久未被访问的那一页,认为那些刚被使用过的页面可能还要立即被使用,而那些在较长时间内未被使用的页面可能不会立即使用。模拟了程序执行的局部属性,既考虑了循环性又兼顾了顺序性,但严格实现的代价大(需要维持特殊队列),模拟实现的方法为:
- 最近未使用页面替换算法(NRU)/引用位法:每页建一个引用位,供硬件使用;设置一个时间间隔中断,周期性地把所有页的引用位置0;地址转换时,页引用标志置1;淘汰页面时,从页引用标志为0的页中间随机选择。该方法开销小但时间间隔多长是个难点。
- 最不经常使用页面替换算法(NFU)/计数法:基于时间间隔中断,并给每一页设置一个页引用计数器;时间间隔中断发生后,所有计数器置0;每访问页1次就给计数器加1;淘汰页面时,选择计数值最小的页面淘汰。
- 计时法:基于时间间隔中断,为每页增设一个计时单元;每当页面被引用时把当前绝对时间置入计时单元;时间间隔中断发生后,所有计时单元全部清除;淘汰页面时,选择绝对时间最小的页面淘汰。
- 老化算法:基于时间间隔中断,为每个页设置一个多位寄存器;每当页面被访问时,寄存器最左边位置0;时间间隔中断发生后,所有寄存器右移一位;淘汰页面时,选择值最小的寄存器对应的页面淘汰。
- 第二次机会页面调度算法(SCR):淘汰最先进入内存的页面如果最近还在使用,仍然有机会像新调入页面一样留在内存中。页面调入主存时,其引用标志位置1;访问主存页面时,其引用标志位置1;淘汰页面时,从FIFO页面队列对首开始扫描,把所遇到的引用标志位是1的页面的引用标志位清0,并移至队尾(看作新调入的页再给一次机会),把所遇到的引用标志位是0的页面淘汰(其最早进入内存且最久未被使用)。
- 时钟页面替换算法(Clock):采用循环队列机制构造页面队列,形成了一个类似于钟表面的环形表。队列指针则相当于钟表面上的表针,指向可能要淘汰的页面。使用页引用标志位。页面调入主存时,其引用标志位置1;访问主存页面时,其引用标志位置1;淘汰页面时,从指针当前指向的页面开始扫描循环队列,把所遇到的引用标志位是1的页面的引用标志位清0,并跳过,把所遇到的引用标志位是0的页面淘汰,指针推进一步。
页表及相关硬件机制在地址转换、存储保护、虚拟地址访问中发挥了关键作用
为页式存储管理设置专门硬件机构内存管理单元MMU:CPU管理虚拟/物理存储器的控制线路,把虚拟地址映射为物理地址,并提供存储保护,必要时确定淘汰页面
- 页号:虚拟地址页号
- 进程标志符:使用该页的进程号(页号和进程标志符结合起来标志一个特定进程的虚拟地址空间的一页
- 标志位:有效、引用、修改、保护和锁定等标志信息
- 哈希链指针
- MMU通过哈希表把进程标识和虚页号转换成一个哈希值,指向IPT的一个表目
- MMU遍历哈希链找到所需进程的虚页号,该项的索引就是页架号,通过拼接位移便可生成物理地址(多个页号经哈希函数转换后可能获得相同哈希值,需要利用哈希链处理这种冲突)
- 若遍历整个反置页表中未能找到匹配页表项,说明该页不在内存,产生缺页中断,请求操作系统调入
段式存储管理
段式程序设计:把一个程序设计成多个段(代码段、数据段、堆栈段等),用户可以自己应用段覆盖技术扩充内存空间使用量。每一段都可以从“0”开始编址,段内的地址是连续的。分段存储器的逻辑地址由段号:单元号组成。
这一技术是程序设计技术,不是OS存储管理的。段号和单元号是用户程序自己设计的,用户可控制,而页号和单元号是系统切割的用户不知道。
段式存储管理基于可变分区存储管理实现,一个进程要占用多个分区,硬件需要增加一组用户可见的段地址寄存器(代码段、数据段、堆栈段,附加段),供地址转换使用;存储管理需要增加设置一个段表,每个段占用一个段表项,包括:段始址、段限长,以及存储保护、可移动、可扩充等标志位。
通过不同进程段表中的项指向同一个段基址来实现段的共享。对共享段的信息必须进行保护,如规定只能读出不能写入,不满足保护条件则产生保护中断。
段式虚拟存储管理:把进程的所有分段都存放在辅存中,进程运行时先把当前需要的一段或几段装入主存,在执行过程中访问到不在主存的段时再把它们动态装入。段式虚拟存储管理中段的调进调出是由OS自动实现的,对用户透明,而段覆盖技术则是用户控制的主存扩充技术,OS不感知。
段式虚拟存储管理需要进行段表的扩充
-
特征位: 00(不在内存)01(在内存)11(共享段)
-
存取权限: 00(可执行)01(可读)11(可写)
-
扩充位: 0(固定长)1(可扩充)
-
标志位: 00(未修改)01(已修改)11(不可移动)
段页式存储管理
段式存储管理可以基于页式存储管理实现,每一段不必占据连续的存储空间,可存放在不连续的主存页架中
段表不再记录基址与限长,而是记录页表的基址与限长
每一段有一个页表。逻辑地址由段号:段内页号:页内偏移地址构成
还可以扩充为段页式虚拟存储管理,装入部分段,或者装入段中部分页面