1. 存储管理功能
1.1 地址映射
定义:把程序中的虚拟地址/逻辑地址
转换成内存真实的地址/物理地址
的过程
地址映射的实现方式
这里提前声明:
- VA: 逻辑地址 Virtual Address
- BA: 装入地址 Base Address
- MA: 物理地址 Memory Address/Phisical Address
固定地址映射
静态地址映射
程序装入时由操作系统完成逻辑地址到物理地址的映射。
MA = BA + VA 即 物理地址 = 基地址 + 偏移地址
例:加入逻辑地址 VA = X, X存放内容即为(X)且(X)=1234。基地址为BA。则有
MA = BA + X
静态地址映射的特点
- 程序执行前确定
- 程序装入后不能移动,如果要移动必须放回原来的位置
- 程序占用连续的内存空间
动态地址映射
定义:在程序执行过程中将逻辑地址转换为物理地址。
例如: MOV AX, [500] ; 访问500单元时才执行地址转换
注意:如果程序有移动,BA可能会有改变,自动计算新的MA。如下图示:
特点
- 程序占用的内存空间可动态变化,要求及时更新BA
- 程序不要求占用连续的内存地址空间,每段放置基地址BA系统知道
- 以便于多个进程共享代码(共享代码作为独立的一段存放)
1.2 虚拟存储
虚拟存储是面向用户的虚拟封闭的存储空间。
解决问题:
- 程序过大时内存不够,无法运行
- 多个地址并发执行导致地址冲突,不能运行
1.2.1 虚拟内存管理的目标
- 使得大程序能在较小的内存中运行
- 使得多个程序能在较小的内存总运行
- 使得多个程序并发运行时地址不冲突
- 使得内存的利用效率高:无碎片化,共享方便
1.3 内存分配功能
为程序运行分配足够的内存空间
需要解决的问题:
- 放置策略
- 程序调入内存时将其放到哪个内存区
- 调入策略
- 何时将运行的代码和要访问的数据调入内存
- 淘汰策略
- 内存不够时,释放哪些代码或数据腾出内存空间
1.4 存储保护功能
保证在内存中的多道程序只能在给定的存储区域内活动且互不干扰。
- 防止访问越界
- 防止访问越权
1.4.1 实现方法:界址寄存器
- 在CPU中设置一对下限寄存器和上限寄存器,存放程序在内存中的上下限地址。
- 基址寄存器和限长寄存器
2. 物理内存管理
2.1 分区内存管理
- 单一分区存储管理
- 分区存储管理
- 固定分区
- 动态分区
2.1.1 单一分区存储管理(部分区存储管理)
定义:用户区不分区,完全被一个程序占用。如DOS
2.1.2 固定分区存储管理
分区存储管理是指把用户区内存划分为若干个大小不等的分区,供不同的程序使用。适合单用户单任务系统
固定分区定义:把内存固定地划分为若干个大小不等的分区。每个分区的大小和位置都固定,系统运行期间不再重新划分。
分区表
记录分区的位置,大小和使用标志。如下图示:
使用特点
- 在程序装入前,内存已经分区且不再改变。
- 每个分区大小不同适应不同代销的程序。
- 系统要维护分区表。
缺点
- 浪费内存:程序比所在分区小时会产生内存碎片
- 大程序可能无法运行:程序比最大分区还大
但是如果知道程序的大小、个数、装入顺序时,内存的使用效率很高。
2.1.3 动态分区
定义:在程序装入时创建分区,使分区的大小刚好和程序的大小相等。
图:
2.2 分区放置策略
2.2.1 分区的分配
首先要介绍一下啊分区表的概念。空闲区表是用来描述内存空闲区的位置和大小的数据结构。
分配过程(假定用户要求的空间大小为s)
- 从空闲区表的第1个区开始,寻找>= s的空间去
- 找到后从分区中分割出大小为s的部分给用户使用
- 分割后的剩余部分作为空间去仍然记录在空闲区表中
注意:分割空闲区时一般从底部分割。
2.2.2 空闲区如何排序-放置策略
- 按照空闲区位置递增/减排序
- 按照空闲区大小递增/减排序
2.2.3 分区回收
回收程序释放区,登录到空闲表中,以便再分配。
回收过程如下图所示,其中
- 白色区代表当前空闲区
- 红色区代表释放区
- 灰色区代表占用区
2.3 内存覆盖技术
内存分区
- 常驻区:被某段单独固定地占用,可划分多个
- 覆盖区:能被多段共用,可划分多个
覆盖的缺点
- 编程复杂:程序员需要划分模块并确定覆盖关系
- 程序执行时间长:从外存装入内存耗时
- 程序模块可能比覆盖区大小还大导致无法装入
3. 虚拟内存管理
3.1 页式虚拟内存管理概念
3.1.1 物理内存(即实内存)管理
特点 | 缺点 | |
---|---|---|
1 | 源程序必须直接使用物理地址 | 程序间容易访问冲突 |
2 | 程序必须全部装入内存才能运行 | 内存太小则程序无法运行 |
3 | 程序占用连续的一片内存 | 会产生内存碎片 |
4 | 多个程序同时运行容易互相干扰 | 不安全 |
改善物理内存的相关技术有
- 内存拼接
- 对换技术
- 覆盖技术
3.1.2 虚拟内存管理
注:虚拟内存的大小是由内存+外存以及计算机最大寻址位数确定的。它的大小为min(内存+外存,2的最大寻址位数次方)。假如用户使用的是64位系统,内存为8G,外存为500G,则最大虚拟内存为2^64 = 16G。一般而言最大虚拟内存就为2的系统的最大寻址数次方,因为外存一般都很大…每个进程拥有的虚拟空间都为最大虚拟内存大小。
实现思路
我们知道,程序运行有一定的特点,如:
- 程序在有限的时间内访问的代码和数据往往几种在有限的地址范围内
- 把程序一部分装入内存在较大概率上也足够其运行一小段时间
因此系统可以在程序运行时只将很小一部分代码和数据装入内存中。其他的代码在需要时再装入,不再运行的代码和数据则从内存中清除。这样即使是较大的程序也可以在较小的内存中运行。
虚拟内存的管理方式
- 页式虚拟存储管理
- 段式虚拟存储管理
- 段页式虚拟存储管理
页式虚拟存储管理
把进程空间和内存空间划分为等大小的小片
- 小片的典型大小:4K、2K、1K
- 进程的大小 - 页
- 内存的大小 - 页框
进程装入和使用内存的原则
- 内存以页框为单位分配使用
- 进程以页为单位装入内存
- 只把程序部分页装入内存便可运行
- 页在内存中占用的框可以不相邻
- 需要新页时,按需从硬盘调入内存
- 不再运行的也及时删除,腾出内存空间
3.2 页表和页式地址映射
3.2.1 页式系统中的地址
虚拟地址VA可以分解为
- 页号 P(VA所处页的编号 = VA / 页的大小)
- 页内偏移 W(VA所在页中的偏移 = VA % 页的大小)
即VA = P * page_size + W。实际计算时不会用 /
,%
来计算除法和取余,而是采用位运算的方式,这样效率更高。
假如页的大小为1k = 2^n,即n=10,则有
- P = VA >> n
- W = VA && (2^ n-1)
例: 假设某段代码的虚拟地址 VA = 2500,页面大小为 1k = 2^10,则有
- P = 2500 / 1024 = 2
- W = 2500 % 1024 = 452
3.2.2 页面映射表 / 页表
页面映射表是记录页与页框的对应关系表,也叫页表。如下图示:
页号 | 页框号 | 页面其他特征 |
---|---|---|
0 | 5 | … |
1 | 32 | … |
2 | 19 | … |
3.2.3 页式地址映射
虚拟地址映射到物理地址过程:
- 从VA分离页号P和页内偏移W
- 查页表:以P为索引查页框号
- 计算物理地址MA,MA = P‘ * page_size + W,page_size一般为4k
3.3 快表技术和页面共享技术
3.3.1 快表机制
- 快表:页表存放在Cache中
- 慢表:页表存放在内存中
快表是慢表部分内容的复制
。在地址映射的时候会先访问快表
,若在快表中找到了所需数据,则“命中
”,若没有“命中”,则需访问慢表,同时更新快表
。要想具有较高的命中率,就应该合理选择页面调度策略。
3.3.2 页面共享
- 在不同进程的页表中填上相同的页框号,多个进程就可以访问相同的内存空间,从而实现页面共享
- 共享页面在内存中只有一份真实存储,节省内存
3.4 缺页中断
当前计算机的分级存储体系
CPU先从Cache中查找数据,如果没有命中再去内存中查找,若内存没有数据,则从外存调入到内存中。从内存查找到了后更新Cache。
3.4.1 页表扩充
上文提到过页表的结构:
除了上图汇总的这种页表结构之外,还有扩充中断位和辅存地址的页表和带访问位和修改位的页表,如下图所示:
3.4.2 缺页中断
定义:在地址映射的过程中,当要访问的目的页不在内存时,系统产生异常中断 ——缺页中断。
缺页中断处理过程:
- 中断程序把所缺的页从页表指出的辅存地址调入内存的某个页框中
- 更新页表中该页对应的页框号
- 修改中断位为0
缺页率:
- 缺页率 f = 缺页次数 / 访问页面总次数
- 命中率 = 1 - f
思考一个问题,在下面的程序中,我们有时候会用计时器计算某个函数或是程序的运行时间,但是这样并不精确。原因是程序是分页的,有可能程序划分为多个页且没有一次性全部导入内存中,所以在程序的执行过程中,可能产生缺页中断,这就会产生一次或多次IO操作,从而增加程序运行的时间。
3.5 页面淘汰策略
淘汰策略指的是系统选择淘汰哪一页的规则。好的淘汰策略应为具有较低的缺页率or较高的命中率
,且页面在内存和辅存中的交换(页面抖动
)较少。
3.5.1 页面淘汰算法
算法 | 描述 |
---|---|
最佳算法 OPT | 淘汰以后不再需要或者最远的将来才用到的页面(理论最佳,实际无法实现) |
先进先出淘汰算法 FIFO | 淘汰在内存中停留时间最长的页面 |
最久未使用淘汰算法 LRU | 淘汰最长时间未使用的的页面 |
最不经常使用算法 LFU | 选择到当前时间未知访问次数最少的页面,每页设置访问计数器,每次页面被访问时将访问计数器+1。当发生缺页中断时,淘汰计数值最小的页面 ,并将所有计数清零 |
3.6 缺页因素与页式系统缺点
3.6.1 页面的大小选择
- 页面太大:浪费内存
- 页面太小:页面增多,页表长度增加,浪费内存;换页频繁,系统效率低
- 页面的常见大小:1KB, 2KB, 4KB
上面是常见的两种访问数组的方式,二位数组的在内存中的存储方式为按行存放,如上图所示。如果用第一种方式(myArray[i][j]
)方式访问数组的话,指针将是顺序依次访问。但是如果按第二种方式的话,每次访问某个地址空间都要间隔10000个内存块。Int大小为4字节(4B),则MyArray的大小为10K * 4B = 40 KB
,假如系统的页大小为4KB,那么第二种方式,每次访问数组的一项都要换页,效率低浪费时间。
3.6.2 页式系统的不足
- 页面划分无逻辑含义
- 页的共享不灵活
- 容易产生页内碎片
3.7 段式和段页式虚拟存储
3.7.1 段式存储管理
进程分段
把进程按照逻辑意义划分为多个段,每个段有段名,长度不固定。进程由多个段组成。
例:一个具有代码段、数据段、堆栈段的进程可以像下图方式存储:
段式内存管理系统的内存分配:
- 以段为单位装入,每段分配连续的内存
- 段和段不要求相邻
段式系统的虚拟地址:
- 段式虚拟地址VA 包含段号S 和 段内偏移W
- VA:(S, W)
段表(Segment Memory Table)
段号 | 段长 | 基地址(段在内存的首地址) |
---|---|---|
S | L | B |
段式地址的映射过程
- 由逻辑地址VA分离出(S, W)
- 查询段表(检索段号S,查询该段
基地址B
和长度L
) - 物理地址 MA = B + W
段表包含
- 基本字段:段号、长度、基址
- 扩展字段:中断位、访问位、修改位、R/W/X(读、写、执行权限)
段式系统的缺点
- 段需要连续的内存
- 段的最大尺寸收到内存大小的限制
- 在辅存中管理可变尺寸的段比较困难
3.7.2 段页式存储管理
段页式就是在段中再划分页面。
段页式地址的映射
同时采用段表和页表实现地址映射。
- 系统为每个进程建立一个段表
- 系统为每个段建立一个页表
- 段表给出每段的页表基址和页表长度
- 页表给出每页对应的页框