7.1 内存管理功能
存储器功能需求
- 容量足够大
- 速度足够块
- 信息永久保存
- 多道程序并行
多道程序并行带来的问题
共享: 代码和数据共享,节省内存
保护: 不允许内存中的程序相互非法访问
实际存储体系
三级存储体系
Cache(快,小,贵) + 内存(适中) + 辅存 (慢,大,廉)
基本原理
- 当内存太小不够用时,用辅存来支援内存
- 暂时不运行的模块换出到辅存上,必要时再换入内存
存储管理的功能
- 地址映射
- 虚拟存储
- 内存分配
- 存储保护
1. 地址映射
定义
把程序中的地址(虚拟地址/虚地址/逻辑地址)变换成内存的真实地址(实地址/物理地址)的过程.
地址重定位,地址重映射.
方式
- 固定地址映射: ( 特点:)
- 静态地址映射
- 动态地址映射
固定地址映射
定义: 编程或者编译时确定逻辑地址和物理地址的映射关系
特点
- 程序加载时必须放在指定的内存区域
- 容易产生地址冲突,运行失败
静态地址映射
定义: 程序装入时由操作系统完成逻辑地址到物理地址的映射
- 逻辑地址: VA(Virtual Addr.)
- 装入基址: BA(Base Addr.)
- 物理地址: MA( Memory Addr.)
特点
- 程序运行之前确定映射关系
- 程序装入后不能移动:如果移动必须放回原来位置
- 程序占用连续的内存空间
动态地址映射
定义: 在程序执行过程中把逻辑地址转换为物理地址
映射过程如果程序有移动,BA可能会改变,自动计算新的MA
MA=BA+VA
特点
- 程序占用的内存空间可动态变化:要求及时更新基址BA
- 程序不要求占用连续的内存空间:每段放置基址BA系统应该知道
- 便于多个进程共享代码:共享代码作为独立的一段存放
缺点
- 硬件支持(MMU: 内存管理单元)
- 软件复杂
2. 虚拟存储
解决的问题
- 程序过大或过多时,内存不够,不能运行
- 多个程序并发时地址冲突,不能运行
虚拟内存的概念
虚拟内存是面向用户的虚拟封闭存储空间
- 线性地址空间
- 容量4G=232Byte
- 封闭空间(进程空间)
- 和物理地址分离(地址无冲突)
- 程序员编程时使用线性虚拟地址
虚拟内存管理的目标
- 使得大的程序能在较小的内存中运行
- 使得多个程序能在较小的内存中运行
- 使得多个程序并发时地址不冲突
- 使得内存录用率高:无碎片,共享方便
7.2 物理内存管理
7.2.1 分区内存管理
- 单一区存储管理
- 分区存储管理:固定分区;动态分区
单一区存储管理
定义: 用户区不分区,完全被一个程序占用
优点: 简单,不需复杂硬件支持,适用于单用户单任务OS
缺点: 程序运行占用整个内存,即使小程序也是如此(内存浪费,利用率低)
分区存储管理
定义
- 把用户区内存划分为若干大小不等的分区,供不同的程序使用
- 适合单用户单任务系统
固定分区: 把内存固定地划分为若干个大小不等的分区供各个程序使用,分区表记录分区的位置,大小和使用标志.
动态分区: 程序装入时创建分区,使分区的大小刚好与程序的大小相等.特点:分区动态建立
7.2.2 分区放置策略
空闲区表:描述内存空闲区的位置和大小的数据结构
分配过程(假定用户要求的空间大小为s)
- 从空闲区表的第1个区开始,寻找>=s的空闲区
- 找到后从分区分割出大小为s的部分给用户使用
- 分割后剩余部分作为空闲区仍然登记在空闲区表中
- 注意:分割空闲区时一般从底部分割
放置策略
- 按空闲区位置(首址)递增排序(首次适应算法)
- 按空闲区位置递减排序
- 按空闲区大小递增排序(最佳适应算法)
- 按空闲区大小递减排序(最坏适应算法)
首次适应法
空闲区表按首址递排序
特点:
- 尽可能地先使用低地址空间
- 当需要较大分区时在高地址空间有较大的满足可能性
最佳适应法
前提:按照大小递增排序
特点:
- 尽可能先使用较小的空闲区,保留大的空闲区.
- 当需要较大分区时有较大的满足可能性
最坏适应法
前提: 空闲区表按大小递减排序
优点: 大空闲区分割后剩下部分还是很大,还能装下较大的程序.
特点: 仅作一次查找就可找到所要分区
分区的回收
功能: 回收程序释放分区(释放区), 登记到空闲区表中,以便再分配.
回收算法
- 要考虑释放区与现有空闲区 是否相邻?
- 若释放区与现有空闲区不相邻,则直接插入空闲区表
- 若释放区与现有空闲区相邻,则与空闲区合并后更新空闲区表
7.2.3 内存覆盖技术
目的: 在较小的内存空间中运行较大的程序
内存分区
常驻区: 被某段单独且固定地占用,可划分多个
覆盖区: 能被多段公用覆盖,可划分多个
覆盖的缺点:
- 编程复杂,程序员划分程序模块并确定覆盖关系
- 程序执行时间长,从外村装入内存耗时
7.2.4 内存交换技术
原理
- 内存不够时把进程写到磁盘(换出/Swap Out)
- 当进程要运行时重新写回内存(换入/Swap In)
优点
- 增加进程并发数
- 不考虑程序结构
缺点
- 换入和换出增加CPU开销
- 交换单位太大(整个进程)
需要考虑的问题
- 减少交换传送的信息量(模块/段)
- 外存交换空间的管理方法
- 程序换入时的地址重定位
7.2.5 内存碎片
过小的空闲区,难实际利用; 内存碎片会降低内存有效利用率.
动态分区的缺点
- 容易产生内存碎片:内存反复分配和分割
- 首次适应法|最佳适应法|最坏适应法
解决碎片的办法1
- 规定门限值
- 分割空闲区时,若剩余部分小于门限值,则此空闲区不进行分割,而是全部分配给用户
解决碎片的办法2:内存拼接技术
- 将所有空闲区几种一起狗哦成一个大的空闲区
拼接的时机
- 释放区回收的时候- 拼接频率过大,系统开销大
- 系统找不到足够大的空闲区时 - 空闲区的管理复杂
- 定期 - 空闲区的管理复杂
拼接技术的缺点
- 消耗系统资源
- 离线拼接
- 重新定义作业
解决碎片的办法3: 解除程序占用连续内存才能运行的限制
把程序拆多个部分装入不同分区,充分利用碎片
7.3 虚拟内存管理
7.3.1 页式虚拟内存管理概念
虚拟内存管理的目标
- 使得大的程序能在较小的内存中运行
- 使得多个程序能在较小的内存中运行
- 使得多个程序并发运行时地址不冲突
- 使得内存利用效率高:无碎片,共享方便
虚拟内存管理的实现思路
在程序运行时,只把当前必要的很小一部分代码和数据装入内存中.其余代码和数据需要时再装入.不再运行的代码和数据及时从内存删除.
程序运行的局部性
- 程序在一个有限时间段内访问的代码和数据往往集中在有限的地址范围内
- 把程序一部分装入内存在较大概率上也足够让其运行一小段时间.
典型虚拟内存管理方式
- 页式虚拟存储管理
- 段式虚拟存储管理
- 段页式虚拟存储管理
页式虚拟存储管理
概念
把进程空间(虚拟)和内存空间划成等大小的小片
- 小片的典型大小: 1K, 2K或4K
- 进程的小片-页(虚拟页或页面)
- 内存的小片-页框(物理页)
进程装入和使用内存的原则
7.3.2 页表和页式地址映射
虚拟地址(VA)可以分解成页号P和页内偏移W
页号: VA所处页的编号=VA/页的大小
页内偏移(W): VA在所处页中的偏移=VA%页的大小
例: VA=2500;页面大小1K
P =2500/1024=2
W=2500%1024=452
页面映射表
记录页与页框之间的对应关系,也叫页表.
- 页号:登记程序地址的页号
- 页框号:登记页所在的物理页号
- 页面其他特征: 登记含存取权限在内的其他特征
页式地址映射
功能: 虚拟地址(页式地址)转换为物理地址
过程
- 从VA分离页号P和页内偏移W
- 查页表:以P为索引查页框号P'
- 计算物理地址MA
MA=P' ✖ 页大小+ W
例子
7.3.3 快表技术和页面共享技术
快表机制(Cache)
快表的概念
- 慢表:页表放在内存中
- 快表: 页表放在Cache中
快表的特点:
- 容量小,访问快,成本高
- 快表式慢表的部分内容复制
- 地址映射时优先访问快表
- 合理的页面调度策略能使快表具有较高命中率
若在快表中找到所需数据,则称为"命中"; 若没有命中时,需要访问慢表,同时更新快表
快表机制下地址映射过程
页面的共享
例子:文本编辑器占用多少内存
文本编辑器: 150kb 代码段和 50kb 数据段,有10进程并发执行该文本编辑器
占用内存:= 10✖(150+50)kb=2MB
如果采用代码段共享,代码段在内存只有一份真实存储,占用内存=150+ 10✖50=650kb
页面共享原理
- 在不同进程的页表中填上相同的页框号,多个进程能访问相同的内存空间,从而实现页面共享
- 共享页面在内存只有一份真实存储,节省内存
7.3.4 缺页中断
分级存储体系: Cache+内存+辅存
页表扩充-带中断位的页表
扩充中断位和辅存地址的页表.中断位I-标识该页是否存在内存,若i=1,不在内存;i=0, 在内存. 辅存地址-该页在辅存上的位置
页表扩充-带访问位和修改位的页表
访问位-标识该页最近是否被访问.0:最近没有被访问; 1:最近已被访问
修改位-标识该页的数据是否已被修改.0:该页未被修改; 1: 该页已被修改
缺页中断
定义:
- 在地址映射过程中,当所要访问的页不在内存时,则系统产生异常中断-缺页中断
缺页中断处理程序
- 中断处理程序把所缺的页从页表指出的辅存地址调入内存的某个页框中,并更新页表中该页对应的页框号以及修改中断位I为0.
访存指令的执行过程(含缺页中断处理)
缺页(中断)率
- 缺页率f=缺页次数/访问页面总次数
- 命中率=1-f
7.3.5 页面淘汰策略
淘汰策略:选择那一页的规则称淘汰策略
页面抖动
- 页面在内存和辅存间频繁交换的现象
- "抖动"会导致系统效率下降
好的淘汰策略
- 具有较低的缺页率
- 页面抖动较少
常用的淘汰算法
- 最佳淘汰算法(OPT算法)
- 先进先出淘汰算法(FIFO算法)
- 最久未使用淘汰算法(LRU算法)
- 最不经常使用(LFU)算法
最佳淘汰算法(OPT)
淘汰以后不再需要或最远的将来才会用到的页面.
特点: 理论上最佳,实践中无法实现.
先进先出淘汰算法(FIFO)
淘汰在内存中停留时间最长的页面
优点:实现简单
缺点: 1, 进程只有按顺序访问地址空间时页面命中率才最理想; 2, 异常现象,对于一些特定的访问序列,随分配的页框增多,缺页率反而增加!
最久未使用淘汰算法(LRU)
思想:淘汰最长时间未被使用的页面
最不经常使用(LFU)算法
算法原则
- 选择到当前时间为止被访问次数最少的页面
- 每页设置访问计数器每当页面被访问时,该页面的访问计数器加1
- 发生缺页中断时,淘汰计数值最小的页面,并将所有计数清零.
7.3.6 缺页因素与页式系统缺点
缺页的因素
- 淘汰算法
- 分配给进程的页框数
- 页本身的大小
- 程序的编制方法(局部越好,越不容易缺.跳转或分支越多越容易缺页)
页面太大: 浪费内存,极限是分区存储;
页面太小: 页面增多,页表长度增加,浪费内存;换页频繁,系统效率低
页式系统的不足
- 页面划分无逻辑含义
- 页的共享不灵活
- 页内碎片
7.3.7 段式和段页式虚拟存储
进程分段
把进程按逻辑意义划分位多个段,每段有段名,长度不定.进程由多段组成.
例,一个具有代码段, 数据段,堆栈段的进程
段式内存管理系统的内存分配
以段为单位装入,每段分配连续的内存. 但是段和段不要求相邻
段式虚拟地址VA包含段号S和段内偏移W. VA: (S, W)
段式地址的映射机制
段表(SMT,Segment Memory Table)
- 记录每段在内存中映射的位置
- 段号S: 段的编号(唯一)
- 段长L: 该段的长度
- 基地址B: 该段在内存中的首地址
段式地址映射过程
- 由逻辑地址VA分离出(S,W)
- 查询段表: 检索段号,查询该段及地址和长度
- 物理地址MA=B+W
段表的扩充
- 基本字段: 段号,长度,基址
- 扩展字段: 中断位,访问位,修改位, R/W/X
段的共享
- 共享段在内存中只有一份存储
- 共享段被多个进程映射到各自段表
- 需要共享的模块都可以设置为单独的段
段式系统的缺点
- 段需要连续的存储空间
- 段的最大尺寸受到内存大小的限制
- 在辅存中管理可变尺寸的段比较困难
段式系统 VS 页式系统
地址空间的区别
- 页式系统:一维地址空间
- 段式系统: 二维地址空间
段与页的区别
- 段长可变; 页面大小固定
- 段的划分有意义; 页面无意义
- 段方便共享; 页面不方便共享
- 段用户可见; 页面用户不可见
- 段偏移有溢出; 页面偏移无溢出
段页式存储管理
在段式存储管理中结合页式存储管理技术
段页式系统的地址构成: 段号,页号,页内偏移
- 逻辑地址: 段号S, 页号P 和页内位移W
- 内存按页划分,按页装入.
7.4 Intel CPU与Linux内存管理
7.4.1 Intel CPU物理结构
实模式
- 20位: 1M内存空间
- 地址表示方式: 短地址(16位):偏移地址(16位)
- 短地址4位对齐
保护模式
- 32位地址空间: 4G内存
- 支持多任务,任务切换,上下文保护
- 进程隔离:代码和数据的安全
- 支持分段机制和分页机制
- 新的寄存器
控制寄存器
CR0
CR2: 如果发生缺页,引发缺页的线性地址保存在CR2中
CR3: 包含页目录基址: 高20位
X86 CPU 架构下的三种地址
- 逻辑地址: 汇编语言(段: 偏移)
- 线性地址: 由逻辑地址转换得到
- 物理地址: 未分页 线性地址==物理地址; 分页 线性地址 != 物理地址
地址转换,由MMU(Memory Mangement Unit)执行地址映射过程
7.4.2 Intel CPU段机制
段: 一段连续内存
段描述符
- 段的属性, 8字节
- 段基址
- 段界限
- 段属性
- 段类型
- 访问该段所需最小特权级
- 是否在内存
描述符表
- 存放描述符的数组
- 长度: 8字节的整数倍
全局描述符表 GDT:包含所有进程可用的段的描述符.系统仅1个GDT
局部描述符表LDT:包含与特定进程有关的描述符,每个进程有自己的LDT
中断描述符表IDT:包含中断服务程序的描述符,类似中断向量表
选择子
选择子用于选择GDT/LDT中的某个描述符,存放在段寄存器中,高13位是整数索引,13位
构成: 索引域,1位; TI域,特权级别域,2位.
7.4.3 Linux 页面机制
硬件分页
分页
- Intel CPU的页:4KB
- 通过设置CR0的PG位开启分页功能
- 分页:线性地址->物理地址
- 在MMU中进程分页
二级页表
为了对小页表进行管理和查找,另设置一个叫页目录的表,记录每个小页表的存放位置(即页框号)
页目录是一个特殊页表,每个记录存放的是小页表的编号和其所在的页框号之间的对应关系
页目录:一级页表或外部页表;小页表:二级页表
Window NT 采用二级页表的结构,如下
二级页表地址映射特点
- 访问数据需要三次访问内存
- 页目录调入内存
- 页表按需要调入主存
- 页面,页表,页目录的大小都刚好4K(占1个页框)
Linux三级页表结构
7.4.4 Linux对段的支持
Linux将4G虚拟空间划分为两个部分
- 用户空间与内核空间
- 用户空间3G: 从0到0xBFFFFFFF
- 内核空间1G: 从0xC0000000到0xFFFFFFFF
Linux段机制