Log[操作系统笔记_PART3]_20.05.27

第三章 内存管理

3.1 无存储器抽象

最早的存储器没有抽象概念,每一个程序都可以直接访问内存。当时的程序执行流程是这样的:程序执行到一条指令,操作系统把需要的程序从磁盘复制到内存中,计算机直接根据指令中的地址去物理内存中找相应的内容,完成相应的操作;执行完毕后在用户终端显示提示符并等待新指令,收到新命令后,把新的程序装入内存,覆盖前一个程序。在这种情况,计算机只支持单进程运行。

3.2 地址空间

Question:地址空间解决了什么问题?

Answer:1)把物理地址暴露给进程,这样用户程序可以寻址内存的每个字节,它们就可以很容易地破坏操作系统

2)不能同时运行多个进程,如果用保护键机制使两个程序可以同时存在于内存中,也会因为每个程序中的指令访问的都是绝对地址而产生崩溃。

3.2.1 地址空间的概念

地址空间为程序创造了一种抽象的内存。地址空间是一个进程可用于寻址内存的一套地址集合;每个进程有自己的地址空间,并且这个地址空间独立于其他进程的地址空间(确保读指令寻址时不会寻到其他进程的地方去)

那么如何给每个程序划分自己的地址空间以达到独立效果呢?

解决问题的办法之一就是动态重定位,简单地把每个进程的地址空间映射到物理内存的不同部分。要实现这个机制需要两个寄存器:基址寄存器和界限寄存器。具体实现办法是:当一个进程运行时,程序的起始物理地址存到基址寄存器中,长度装到界限寄存器中。这时候再来读一条指令,CPU会在把地址发到内存总线之前自动把基址加到进程发出的地址值上;同时会检查程序提供的地址是否等于或大于界限寄存器里的值。

缺点:要进行加法计算

3.2.2 交换技术

前面所说的方法都是基于内存足够的理想化情况,实际上所有进程需要的内存大小远超存储器提供的范围,所以我们就要换一种思路。

要实现交换技术,有两种方案:方案一就是我们接下来要说的简单交换技术,第二种就是虚拟内存(见3.3).

简单交换技术的实现原理就是当进程运行时换入内存,不需要运行时换出至磁盘,再利用基址寄存器和界限寄存器来实现独立。思路很简单,但是因为换入内存的随意性,会使内存产生很多空闲碎片;不仅如此,这种方法还有一个问题就是应该给每个进程分配多大的内存,如果运行过程中内存固定还好说,但如果运行过程中内存动态增长且紧挨着又有别的进程在使用的内存,管理起来就会很麻烦。

有两种管理空闲内存的方法。

1. 使用位图的存储管理

内存被分配为小到几个字节大到几千字节的分配单元。每个单元对应位图中的一位;位图中0表示空闲,1表示占用。

2. 使用链表的存储管理

链表结点由 空闲区/进程的指示标志、起始地址、长度和指向下一节点的指针组成。有了这些元素我们就可以选择一些方式来为进程分配内存。比如首次适配算法、下次适配算法、最佳适配算法等。

3.3 虚拟内存

虚拟内存的出现是为了解决日益增长的软件大小问题。有些软件大小已经大到内存无法容纳,就更别说同时容纳几个程序了。

解决这个问题的初期办法是将程序分割成许多片段,称为覆盖块;程序运行时先装入覆盖管理模块到内存,由该模块进行其他模块的装入和换出。但是把一个大程序分割成小的、模块化的片段是非常耗时和枯燥的,并且易于出错。

3.3.1 虚拟内存的思想

虚拟内存的基本思想是:每个程序都拥有自己的地址空间,这个空间被分割为很多个块,每一块称为一页,每一页有连续的地址范围。这些页面中的一些页面被映射到物理内存。当程序引用到一部分在物理内存中的地址空间时,由硬件立即执行必要的映射。当程序引用到一部分不在物理内存中的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的指令。

虚拟内存这种操作很适合多道程序的处理,当一个程序等待它的一部分读入内存时,可以把CPU交给另一个程序。

3.3.2 分页

前面说到要把程序的地址空间分割为很多个块,有一种分页技术,就是实现这个功能的。

我们把在程序指令中的地址称为虚拟地址,它们构成了一个虚拟地址空间。如果没有虚拟内存,系统会直接将虚拟地址送到内存总线上;而在使用虚拟内存时,虚拟地址会送往内存管理单元,由它负责把虚拟地址映射为物理内存地址。

虚拟地址空间按照固定的大小被分为称为页面的若干单元,在物理内存中对应的单元称为页框。

eg:MOV REG,x

过程:首先将虚拟地址x送到内存管理单元,MMU检测到虚拟地址落在页面y上,然后查看其映射,比如发现其对应的是页框z,这时MMU把地址变成页框z的起址并加上x并送往内存总线,内存就会处理对地址z+x进行的操作。

如果没有找到某个虚拟地址的映射,CPU会陷入操作系统,这个情况就叫做缺页中断。缺页中断时,就要将某个页面的表项(表项存在于页表中,页表存在于MMU中,MMU的查看映射、拼接地址的工作就是依照页表里的信息来进行的)标记为未映射,随后将产生缺页中断的地址所在的页面的表项标识为被映射,并把它映射到空页框中。随后返回开始执行产生缺页中断的那个指令。

3.3.3 梳理进程运行过程中与分页有关的工作

操作系统要在以下四个时间段做与分页相关的工作:进程创建、进程执行、缺页中断、进程终止时。

创建时:操作系统对程序和数据的初始大小进行确认,并为它们创建一个页表(页表是在内存中存储的),进程被换出时页表不需要留在内存中。除此之外,操作系统还需要给在磁盘交换区分配空间并放入程序和数据,以便在一个进程换出时在磁盘上有放置此进程的空间和进行页面交换。有关页表和磁盘交换区的信息存储在进程表中。

执行时:为新进程重置MMU,刷新TLB(快表)。将程序部分或全部装入内存。

缺页中断时:读硬件寄存器判断是哪个虚拟地址造成了缺页中断,计算页面并在磁盘上对页面进行定位、置换。最后回退程序计数器,重新执行该指令。

退出时:释放页表、页面和页面在磁盘上占用的空间。

3.4 页面置换算法

接下来看一下在缺页中断进行页面置换时,如何选择要被置换的页面。

3.4.1 最优页面置换算法

每个页面都以在访问这个页面前所要执行的指令数作为标记。每次置换时应置换标记最大的页面。不过这个算法过于理想化,暂时无法实现。

3.4.2 最近未使用页面置换算法

系统设置两个标记位:R:标记页面有没有被访问 M:标记页面有没有被改写

用这两个位就可以构造一个简单的页面置换算法:启动一个进程时,所有页面的两个位被设置为0,R 被定期地(比如可以在时钟中断时)清零,这样就能区分出来最近没有被访问的页面。

3.4.3 先进先出和第二次机会页面置换算法

先进先出法如其名:置换出最早进入内存的页面,如果有最先进入的页面被频繁使用的状况,就不适合用这个算法。

第二次机会算法是对先进先出的一个升级版:在进行置换时,检查最老页面的R位,如果R位标识为1,则表示该页面最近在使用,先不置换而是将R设置为0.然后把此页面链接到链表的最后端(也就是被当作了最新装入的页面)。

3.4.4 最近最少使用页面置换算法(LRU)

这个算法的思想是在缺页时置换未使用时间最长的页面。为了实现LRU,需要在内存里维护一个所有页面的链表,几乎在每一次进行访问时,都要把一个结点从链表删除再重新插入,这样才能呈现出最近最多使用的在表头,最近最少使用的在表尾的效果,显然是非常耗时的。

3.3.5 老化算法

老化算法是对LRU的升级,在上面我们说到LRU需要频繁对链表进行改动,那么不如换一种方式,放弃链表,转而为每个页面都维护一个计数器。计数器初值为0.在每次时钟中断时,由操作系统扫描内存,先将计数器右移一位,再将每个页面的R位都加到这个计数器的左端。发生缺页中断时,将置换计数器值最小的页面。

TIPS:在页面置换时还要考虑被置换的页面是否在内存中被修改过,如果已经修改,则将新页面写回磁盘;如果没有被修改,直接覆盖掉就好。

3.5 分段

以上基于虚拟内存的讨论都是一维的,但事实上很多情况下,有两个或者多个独立的地址空间比只有一个要好。那么问题来了,假设一个程序编译过程产生了许多表,他们依次分布在地址空间中。然后有几个表会随着编译的进行不断增长,另一个表不断缩小。这时候就可能造成地址空间中留给前几个表的空间不足,而留给另一个表的地址空间还很多,显然不太合理。所以我们需要一个不需要管理扩张和缩小的办法。

这时候就要用到分段。在机器上提供多个相互独立的称为段的地址空间,段长度是动态改变的,因为它独立,所以它增长缩小都不会影响其他段。那么如何在段内进行寻址呢?需要两个要素:段号和段内地址。

3.5.1 段页结合-MULTICS(待写)

3.5.1 段页结合-Intel x86(未完)

纯分段的话会因为交换而产生内存碎片,所以我们一般采用段页结合。这里以Intel x86的实现来进行说明。

x86有16K个独立的段,每个段最多容纳10亿个32位字。它实现虚拟内存的核心是两张表:LDT(局部描述符表,程序独有)和GDT(全局描述符表,所有程序共享)LDT描述程序的段,包括其代码、数据、堆栈等,GDT描述系统段,包括操作系统本身。

为了能访问这个段,程序必须将这个段的选择子装到寄存器中,CS寄存器保存代码段的选择子,DS保存数据段的选择子。选择子的结构是16位数:13位表项编号,一位标识GDT/LDT,2位描述它的特权级。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值