第四章 存储管理
层次化存储体系结构
存储器 | 特点 |
---|---|
第一层 | 存储器 |
第二层 | 高速缓存(Cache) |
第三层 | 主存(内存) |
第四层 | 磁盘 |
操作系统的任务
- 记录存储使用情况
- 分配、回收存储资源
- 内存不够时,数据装入和写回
基本存储管理
分类
- 由于内存不足,需要在内存和磁盘间换进换出(进程、页面置换)
- 不需要换进换出的系统
特点:进程被调入运行后,始终位于内存中,直至运行结束- 没有交换和分页的单道程序
- 固定分区的多道程序
单道程序存储管理
基本思路:内存划分为系统区和用户区,同一时刻只允许一道程序,应用程序和操作系统共享存储器,直至运行结束。
实现方式
(a)早期大型机和小型机:操作系统被放在RAM的最低端;
(b)掌上电脑和嵌入式系统:操作系统被放在了内存地址的最高端,且在ROM里;
(c)早期PC:操作系统被分成两部分,一部分是设备驱动程序,放在最高端的ROM中(基本输入输出系统),另一部分放在内存地址最低端。
固定分区的多道程序系统
基本思路:将内存划为n个分区,每个分区大小可以相等,也可不等。
单个输入队列
缺点:小分区输入是满的,大分区输入队列是空的。
多个输入队列
缺点:要么浪费内存空间,要么小进程会被忽视。
解决方案:至少保留一个小分区让小进程直接运行,或规定一个进程被忽略次数不能超过k次。
固定数量任务的多道程序
操作员手工划分若干个区域,并确定每个区域的起始位置和大小,在整个系统运行期间不改变。
重定位和存储保护
重定位
链接器连接的时候读取地址为绝对地址,造成连接失败。
解决方案:当一个程序被装入内存时,直接对指令代码进行修改,一次性地实现从文件内的相对地址到内存中的绝对地址的转换。为了执行这种操作,链接器必须在可执行文件中包含一个链表或位图,列出各个需要重定位的地址位置。
存储保护
一个恶意程序总可以生产一条新指令去访问他想访问的地址。
解决方案:将内存划分为2KB的块,并为每个块分配一个4位的保护码,在CPU的程序状态字(Program Status Word,PSW)中包含一个4位密钥,当一个进程运行,访问的内存单元的保护码与PSW中的密钥不符,则引起一个陷入。
重定位和存储保护的解决方案
在机器中增加基地址寄存器和边界寄存器
当一个进程被调度时,把该进程所在的分区的起始地址放在基地址寄存器中,并且把这个分区的长度放在边界寄存器中。当进程访问内存单元时,硬件自动加上基地址寄存器的值。
对于每一次内存访问,都要把该地址与边界寄存器的值比较,以防止它去访问分区以外的内存。
交换技术
交换技术:把各个进程完整地调入内存,运行一段时间,再放回磁盘上。
虚拟存储器:进程即使只有一部分内容存放在内存中也能运行。
固定分区和可变分区
可变分区中,分区的个数、位置和大小随进程的进出变化,而固定分区则是固定不变的。
优点:提高内存利用率
缺点:内存的分配、回收和管理更加复杂
内存紧缩技术
把所有的进程都尽可能地往内存地址低端移动,空闲区往高端移动。
可变内存策略
进程分配内存固定,需要扩大内存时需将其移动到内存中一个足够大的空间中。
进程被换进或移动时为其分配一点额外的内存。
基于位图的存储管理
内存被划分为可能小到几个字或大到几千字节的分配单位,每个分配单位对应于位图中的一位,0表示空闲,1表示占用。
位图的大小仅仅取决于内存和分配单位的大小,分配单位越小,位图越大。
缺点:在位图中查找指定长度的连续0串是一个缓慢的操作。
基于链表的存储管理
维持一个已分配和空闲的内存段的链表,链表中的每一个表项都包含下列内容:指明是空洞(H)还是进程(P)的标志,开始地址、长度和指向下一个表项的指针。
内存释放
一个要结束的进程一般有两个邻居(除非是最低端或最高端的),他们可能是进程也可能是空洞,因此当一个进程结束时,内存空间会有四种组合。
内存分配算法
**最先匹配法:**存储管理器沿着内存段链表找到一个大小大于或等于新进程的空洞,除非空洞大小和新进程大小一样,否则会把空洞分为两个部分,一部分装进程,另一部分成新的空洞,并修改相应内容。
**下次匹配法:**每次找到合适的空洞时都会记住当时的位置,下次寻找空洞时从上次结束的地方开始搜索。
**最佳匹配法:**搜索整个链表,找到能够装得下该进程的最小空闲分区。
**最坏匹配法:**每次分配空间总将最大的那个空闲区切去一部分,会导致大进程找不到合适空间。
可以将进程链表和空闲链表分离,但回收会更加复杂。
可以把空闲链表按照从小到大顺序进行排序,以提高最佳匹配法速度,在这种排序方法下,最先匹配法和最佳匹配法速度一样,而下次匹配法则没有意义。
**快速匹配法:**对于一些常用的请求大小,为他们分别设置各自的链表。
缺点:一个进程结束或被换出时寻找它的邻接块以查看是否可以合并很费时间。
虚拟内存管理
虚拟存储器
程序的代码、数据和栈的总大小可以超过实际可用的物理内存大小,操作系统把当前需要用到的那些部分保留在内存中,而把其余部分保存在磁盘上。
虚拟页式存储管理
分页
虚地址空间被划分成称为“页面(pages)”的单位,在物理存储器中对于的单位称为页框,页和页框总是相同大小的。
由程序产生的地址称为虚拟地址,它们构成了一个虚拟地址空间。如果没有虚拟存储机制,那么虚拟地址就是物理地址,会被直接送到内存总线上;若使用虚拟存储机制,那么虚拟地址被送到存储管理单元(MMU),由它负责把虚拟地址映射为物理地址。
把物理内存划分为许多个固定大小的内存块称为物理页面,或称为页框(frame),
把虚拟地址空间划分为相同大小的块,称为虚拟页面,或简称为页面(page)。
页面的大小要求是2的整数次幂。
在实际的硬件上,会有一个有效位来描述每个虚拟页面是否在内存中。
如果程序访问了一个未被映射的页面,就会引发一个缺页中断(page fault),操作系统会从内存中挑选一个使用不多的物理页面,把它的内容写回到磁盘,从而腾出一个空闲页面,然后把引发缺页的那个虚拟页面装入该空闲页面,并更新地址映射关系。
16位的虚拟地址被划分为4位的页号和12位的偏移量。
在进行地址映射时,使用虚拟页面号作为索引去访问页表,从而得到相应的物理页面号。
如果有效位的值为0,则引发一个缺页中断,陷入到操作系统;
如果有效位的值为1,则将页表中查到的物理页面号复制到输出寄存器的高三位中,再加上输入的虚拟地址中的12位偏移量,构成15位的物理地址。
输出寄存器的内容被作为物理地址送到内存总线。
页表
虚拟地址被分成虚拟页面号(高位)和偏移量(低位)两部分。在地址映射时,使用虚拟页面号作为索引去访问页表,从而得到相应的物理页面号。然后用物理页面号来取代虚拟页面号,与虚拟地址中的偏移量进行组合,从而得到最终的物理地址。
页表的用途就是将虚拟页面映射为相应的物理页面。
页表的两个重要问题:
1.页表可能会非常大
虚拟地址空间为4GB,页面大小可以上百万个。
2.地址映射必须十分迅速
每次内存访问时都必须进行虚拟地址到物理地址的映射。
多级页表
虽然进程的虚拟地址空间很大,但当进程在运行时,并不会用到所有的虚拟地址,所以没有必要把所有的页表项都保存在内存中。
因此可以讲虚拟地址的页面号再进一步划分。
例:虚拟地址0x00403004(十进制4 206 596),该地址位于数据段12292处。
①将地址除以4MB,结果为1,余数为12292,因此PT1字段为1.
②将12292除以4KB,结果为3,余数为4,因此PT2字段为3,偏移量为4.
MMU用PT1访问第一级页表的表项1,对应于虚拟地址4MB~8MB,
在找到第二级页表后,再使用PT2来访问表项3,对应于4MB的12288~16383。
如果该页面未在内存中,则页表项中的有效位的值为0,会触发缺页中断。
如果页面在内存中,那么久吧物理页面号与页内偏移地址4组合,得到最终物理地址。
多级页表优缺点
优点:避免将进程的所有页表一直保存在内存中
缺点:需要多次访问内存以查找页表
页表项的结构
位段 | 说明 |
---|---|
页框号 | 物理页面号 |
有效位 | 表示该页面现在是否在内存中 |
保护位 | 表示允许对这个页面做何种类型访问(只读、可读写、可执行) |
修改位 | 记录页面是否被修改,回收物理页面时会检查 |
访问位 | 记录页面是否被访问过,用于页面置换算法 |
禁止缓存位 | 对于那些页面被映射到设备寄存器而不是常规内存页面很重要 |
关联存储器TLB
程序局部性原理:对于绝大部分的程序,运行时倾向于集中地访问一小部分的页面。
快速查找硬件:
TLB(Translation Lookaside Buffer)或者关联存储器:用来存放那些最常用的页表项,直接把虚拟页面号映射为相应的物理页面号,不需要去访问内存中的页表,缩短了查找时间。
TLB通常位于MMU中,包含了少量的表项,一般不超过64个。每个表项包含了一个页面信息,包括虚拟页面号、访问位、保护码和物理页面号,还有一个位表示该表项是否有效。
当一个虚拟地址到来时,MMU首先会到TLB中查找:
如果能够找到且访问合法,那么直接从TLB中把相应的物理页面号取出来;
如果能找到虚拟页面号但违反了访问权限,则引发一个保护中断;
如果未找到该虚拟页面号,那么就要采用通常办法访问内存中页表,取出相应物理页面号,同时会把TLB中某一表项改为现在这个表项,被改的表项的修改位要复制到页表项中。
反置页表
根据内存中的物理页面号来组织页表,用物理页面号来作为访问页表的索引。有多少个物理页面,就在页表中设置多少个页表项。
例:虚拟地址为64位,页面大小为4KB,物理内存大小为256MB,总页表项的个数等于256MB除以4KB,即65536,在每个页表项中,记录