文章目录
第三章 内存管理
01-内存的基础知识
什么是内存
缓和CPU与硬盘之间的速度矛盾
内存地址从0开始,每个地址对应一个存储单元
存储单元:大小是按字节编址的话就是一字节 8 bit,按字编址存储单元就是一个字(字长决定大小)
给一个8GB的内存问地址长度(多少个二进制位能表示)
8GB相当于 23*230 = 2^33 需要33个二进制位来表示
因为2^33实际上是二进制第34位上表示的1的权值,但0本身也表示一种状态所以可以用33位的二进制表示所有状态,另一个角度看如果用34位的话,最大数又是10000…数字为34位的时候其他位的数就浪费了
指令的工作原理
进程在程序中是有程序段和数据段
例子(并不严谨,仅供理解)
指令(操作码,参数一,参数二)
数据传送指令
操作码就是 代表 数据传送,参数一获得数据的地址(CPU),参数二是给出数据的地址(内存)
加法指令
操作码就是 代表加法指令,参数一是寄存器的地址,参数二是加加给寄存器的值
数据传送指令
操作码就是 代表 数据传送,参数一获得数据的地址(内存),参数二获给出数据的地址(CPU)
这里的地址实际上都用的是相对地址(逻辑地址),因为进程放入内存在哪执行不一定
指令中的逻辑地址转换为物理地址(三种)
三种装入方式
- 绝对装入(编译器完成,没有操作系统)
- 编译的时候就知道具体的物理地址起址,就把自己的相对地址和绝对地址合起来得出物理地址
- 运行在另外一台电脑就废了
- 编译的时候就知道具体的物理地址起址,就把自己的相对地址和绝对地址合起来得出物理地址
- 可重定位装入(静态重定位)(早期多道批处理操作系统)
- 装入模块装入内存的时候,将逻辑地址根据内存的状态进行变换地址
- 分配的地址空间必须是连续的
- 必须分配其要求的全部内存空间(不能4个G的内存玩8个G的游戏)
- 装配完之后就不能移动的,指令写死了相对地址
- 装入模块装入内存的时候,将逻辑地址根据内存的状态进行变换地址
- 动态运行时装入(动态重定位)(现代系统使用的)
- 把地址转换推迟到程序真正要执行的时候再运行
- 装入内存的时候还是逻辑地址,需要一个重定位寄存器存放装入模块存放的起始地址
- 可以将程序分配到不连续的存储区中,在程序运行前只需装入他的部分代码即可运行,程序运行期间,根据动态申请分配内存:便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间(可以4个G的内存玩8个G的游戏)
从写程序到程序运行
(源代码)编辑(目标文件)—— >(机器语言)编译(多个目标模块) ——> (带完整逻辑地址的完整模块)链接(装入模块)——>——>()装入(内存)
链接的三种方式
- 静态链接:在程序运行之前,把各个目标模块和需要的库函数链接成一个完整的可执行文件(装入模块),之后不再拆开
- 装入时动态链接:将各目标模块装入内存的时候,边装入边链接
- 运行时动态链接:程序执行时需要用到目标模块,才对他进行链接,便于修改和更新,便于实现对目标模块的共享
02-内存管理概念
内存空间的分配和回收
内存空间的扩展(空分复用)
地址转换
内存保护
- 两种方法
- 方法一:在CPU设置上下限寄存器,存放进程的上下限地址,进程的指令要访问某个地址的时候,CPU检查是否越界
- 方法二:采用重定位寄存器(基址寄存器)和界地址寄存器(限长寄存器)进行越界检查————其实就相当于上下限地址寄存器
03-覆盖与交换
覆盖技术(退出了舞台)
- 将程序分成多个段,常用的段待在内存,不常用的段在需要的时候调入内存
- 常用的段放在内存一个固定区,调入后知道程序结束都不调出
- 不常用的段放在内存若干个覆盖区中,需要的时候调入内存,不需要的时候调出内存
- 多个模块共享一个覆盖区的时候大小按照最大的来计算
- 认为规定覆盖区代码
- 缺点
- 对用户不透明(看得到)增加了编程负担
交换技术
内外存的调度,中级调度,就是这个体现
换出外存的进程相关的PCB会保留在内存中,进入挂起队列
挂起状态分为就绪挂起和阻塞挂起状态,就是七状态模型(来自于第二章的丁字裤模型)
- 外存空间有对换区,
- 对换区重点考虑IO速度,所以对换区采用连续分配的方式,(学了文件管理章节就理解了)
04-连续分配管理方式
系统为用户进程分配的必须是连续的内存空间
3.1 单一连续分配方式
单一连续分配中,内存分为系统区和用户区,
- 系统区一般在低地址
- 系统区存放操作系统相关数据
- 用户区存放进程相关数据
- 内存中只能有一道用户程序
- 用户程序独占整个用户区空间
- 优点:实现简单;
- 无外部碎片,
- 可以采用覆盖技术扩充内存,不一定要采取内存保护
- 缺点:只适用于单用户单任务的操作系统中;
- 有内部碎片(没有被用到的部分浪费)
- 存储器利用率极低
3.2 固定分区分配
为了内存中能装入多道程序,程序们不会互相干扰,于是
-
把整个用户空间划分为若干个固定大小的分区,
-
每个分区中只装入一道作业
分为两种
- 分区大小相等
- 缺乏灵活性,适合控制多个相同对象的场合
- 分区大小不等
- 增加灵活性,满足不同大小的进程需求,资源充分利用
数据结构:分区说明表
每个表项对应一个分区,按照分区的大小排列,
每个表项包括分区的大小、起始地址、状态(是否已经分配)
每次需要用到就
优点:实现简单,无外部碎片
缺点:
- 用户程序太大只能用覆盖技术,降低性能
- 会产生内部碎片,
3.3 动态分区分配
- 在进程装入内存时动态的创建分区,
- 分区的大小等于进程的需要
a.动态分区分配数据结构
空闲分区表和空闲分区链(只用来表示了空闲的部分,占用多少不记录)
b.动态分区分配算法
下一小节
c.如何进行分区的分配与回收
更改空闲分区数据结构的起始地址和分区大小(某个空闲分区没有了就删除表项)
有相邻的更改空闲分区进行合并操作
内部碎片——分配给某进程的内存区域中,有些部分没有用上
外部碎片——某些空闲分区由于太小而难以利用(可以通过紧凑来处理)
05-动态分区分配算法
动态分区分配算法找到需要的就会铡出需要的区间
-
首次适应算法:从低地址开始找能满足要求的
- 空闲分区地址递增排列,从而顺序查找
- 优点:小空间部分都留在了低地址,可留下大的空闲分区,不用重新排序
- 缺点:索引久
-
最佳适应算法:优先使用更小的
- 实现方法:空闲分区容量递增次序排列,分配时产生了小的分区需要移动分区位置
- 缺点:每次选择最适应的,留下的外部碎片也都是最小的难以利用,要重新排序
-
最坏适应算法:优先使用最大的
- 实现方法:空闲分区按照容量递减排序,分配时改变了dad小的分区要重新排列
- 缺点:缺少较大的连续空闲区,要重新排序
-
邻近适应算法:按地址循环寻找适合的,每次都从上次结束的位置进行查找
- 实现:循环链表
- 优点:减少索引时间,不用重新排序
- 缺点:相对首次适应没有在高地址留下打的空闲分区
06-非连续分配之基本分页存储管理概念
什么是分页存储
- 将内存空间分为一个个大小相等的分区,比如每个分区4kb
- **页框:**每个分区可以称之为(页框、页帧、内存块、物理块(内存块)、物理页面)
- 每个页框有一个编号,即**(页框号、**页帧号、内存块号、物理块(内存块)号、物理页号)从0开始
- 内存块号就是用来计算当前页面之前所有页面的数量,乘以页面大小就是之前所有地址和,因为操作系统一般都是按字节寻址
- 页表:每个进程为了存入内存划分成和页框大小对应的区域,每个区域称为页或者页面,划分完毕需要建立页号和内存块的映射就需要为每个进程建立一张页表,所以刚好放在PCB里面
- 页表就是页号和块号(页框号)的映射,所以题目问到页表项需要多少字节我们就需要算出,内存块有多少,需要有几B几位二进制来表示,
- 重复一遍:页面大小等于内存块大小
- 页号不占用存储空间,因为
- 当我们需要通过页号索引得到某个页表项时,只需要页号乘以页面大小就能得到
求页表项需要多少字节(物理块(内存块)号)多少字节
内存块号的大小取决于一共有多少内存块,一共有多少内存块取决于内存块本身的大小(页面大小)
内存的大小(例如4GB)除以内存块的大小(例如4KB)就能得出一共多少内存块
也就是2的十次乘以2的十次二的二十次。
2的20次需要用0~2^20-1也就是20bit,20bit需要三个字节来存储,
所以一个页表项需要3B
注意,这里是为了索引全部内存空间,而一般来说一个进程只能占用一部分内存,对应的页表也只能对应一部分
分页后逻辑地址到物理地址的转换
页面的起始地址加上偏移量W得到物理物理地址
- 1.获得页面的起始地址
- 查页表根据页号得到块号,算出起始地址(块号*内存块大小)
- 2.获得页面偏移量
- 逻辑地址%页面大小
通过进程的某个逻辑地址和内存块大小可以算出当前逻辑地址对应的页号(逻辑地址/页面长度)和页内偏移量(逻辑地址%页面长度)
页号(逻辑地址/页面长度)
页内偏移量(逻辑地址%页面长度)
- 当页面大小用2的整数幂时,我们用逻辑地址运算时,
- 硬件可以直接把和一个逻辑地址 低位和 页面大小一致的部分当做当前页面的偏移量,超出的部分的大小就是页号
- 比如逻辑地址011 0001如果页面大小为2^4B,这段逻辑地址就来自于011页偏移量为0001也就是十进制的3页偏移量为一 的地址
逻辑地址结构
页号——————页内偏移量
如果有K位表示页内偏移量,代表一个页面的大小时2^k个内存块
如果有M位表示页号,代表该系统中一个进程最多允许拥有2^M个页面
07-基本的地址变换机构
实现逻辑地址转换到物理地址的一组硬件机构的原理和流程
- 系统会有一个页表寄存器,存放页表在内存中的起始地址F和页表长度M((来自于程序的PCB中)
- 起始地址是页表的起始地址,页表长度是页面的总数,用来检查页号有没有越界
① 得到页号(除法)和页内偏移量(余数)
②根据页表长度M检查页号是否越界,(页号从零开始,页表长度从一开始,相等也违法)
③通过页号从页表得到内存块号(页号乘以页表项长度(取决于索引数量))
内存块号就是用来计算当前页面之前所有页面的数量,乘以页面大小就是之前所有地址和,因为操作系统一般都是按字节寻址
④物理地址=内存块号乘以页面大小+W(偏移量)
4GB内存 4kb页面大小的内存前面算出需要3B来表示所有的页面
而实际上个页表也是要在用的时候调入内存存进页框里,
所以页表在存储的时候一个页框4kb也就是4096B,4096%3=1,
别忘了我们是根据页号*页面大小来找到物理块(内存块)号(基于连续分配,但是页框不能越界访问)
那么这时候这个1就难受了是吧,所以这种4GB内存 4kb页面大小一般用四个字节来表示一个页表项,
这样就方便很多,而且仅仅一个页表 也占用不了太多内存
08-具有快表的地址变换机构
20分钟
**快表,也叫联想寄存器(TLB),是一种访问速度比内存块很多的高速缓存TLB,**用来存放最近访问页表项的副本
①快表命中直接从快表中取走内存块号,加上偏移量就能获得物理地址,整个过程只需要一次访存
②快表没有命中则访问某个逻辑地址需要两次访存(两次访问内存(慢表)),访问快表两次(找到页表项还要把他放入快表,以便再次访问)
访问快表一次耗时1us,访问内存一次耗时100us(相当于访问慢表),若快表命中率为0.9,那么访问一个逻辑地址的平均时间是多少、?
( 1+100)*0.9+(1+100+100)*0.1=111us
时间局部性
程序存在大量循环
空间局部性
数据连续存放同一个程序的数据可能在一个页表项里面
09-两级页表
20分钟+17分钟
单级页表存在的问题
-
问题一:页表必须连续存放,页表大的时候需要占用很多连续的页框
把页表根据内存块的大小进行存放再次分页,比如内存块为4KB,内存块号(用于索引的一个页表项的大小)为4B,就是1024个页表项分为一个新的大页表一个页表项。
逻辑地址结构拆分成三段,一级页号占十位,二级页号占十位,从一级页表查询到二级页表在内存块的储存位置,从内存块得到最终页表,然后根据最终页表得到内存块号
-
问题二:没必要让整个页表驻留在内存
- 给每一个页表项增加一个标志位,表示是否存在内存中,不存在就产生缺页中
算一个逻辑地址有几级页表
先算最右边的偏移地址,根据页面大小可以算出索引这个页面所有字节需要的索引位数,比如页面大小为4kb就需要2^12B也就是12个bit,页号区域用逻辑地址总位数减去这个偏移地址总位数就能得出
页面能存放(页面大小/页表项大小)个页表项,由于各级页表大小不能超过一个页面
页表能存放的页表项固定所以,如果想映射下一级页表,页号要能映射到下一级页表的所有页表项也就是和页面能存放的页表项数量一致
所以要分多级根据具体情况来看
2.多级页表需要访存次数更多
n级页表需要访问n+1次内存
10-非连续分配之基本分段存储管理
分段
按照程序自身逻辑在进程的地址空间中划分成若干个随意大小的段,每个段都有一个段名,每段从0开始编址
每个段在内存中占据连续空间,各段之间可以不相邻
按照逻辑功能模块划分,用户编程更加方便,程序的可读性更高
逻辑地址结构
段号————段内地址
段号就是索引所有的段,所以2的(段号长度)次就是这个进程的段数
段内地址占N位代表段内需要N个bit来按字节索引段内字节
也就是一个段有2的N次长
写出来的程序按照逻辑功能模块划分,用户编程更加方便,程序的可读性更高
LOAD 1,【D】|//将分段D中A单元内的值读入寄存器1
这里的D会被程序编译成对应的段号,单元会被程序编译成段内地址
段表
各个逻辑段到实际的物理内存的映射关系
【段号】【段长】【段基址】
和页表相比多了段长,因为段长不固定,但是段表项的大小相同,所以段号还是隐含的
段表项根据逻辑地址段号位数决定,段号位数决定了需要索引多少个段(与段长无关)
段基址根据系统的内存决定,系统内存每一个字节都要寻址,系统有多少字节就需要能索引这些字节地址的bit位
如4GB有2^32个字节,就需要32位逻辑地址来表示
段表寄存器
【段表始址】【段表长度】
整个流程相对于页表查询多了一个段内地址是否超过段长,
和分页的对比
- 页是信息的物理单位(只考虑内存块大小)
- 段是信息的逻辑单位(根据逻辑划分大小)
- 分页主要为了离散分配内存
- ;分段为了方便用户编程的
- 页的大小固定
- 段的大小取决于用户编写的程序
- 分段更容易实现信息的共享和保护(因为某个功能代码按照段分开,比较方便)
- 信息保护指的是在标注某一段部分能被共享的时候,分页的情况会很难标注因为可能可共享的和不可共享的在一个页面
- 分段更容易实现信息的共享和保护(因为某个功能代码按照段分开,比较方便)
11-段页式管理方式
段号位数决定有多少段
页号位数决定每个段有多少页
页内偏移量位数决定页面大小(内存块大小)
段页式中分页的行为是用户不可见的
- 逻辑地址:
- 【段号】【页号】【页内偏移量】 后两个会被系统自动拆分,实际上只需要给【段号】,【段内地址】
有的段长久用更多页面,
12-虚拟内存的基本概念
比交换技术和覆盖技术更先进的虚拟内存技术
上面这些所有的存储管理方式有两个特征,
-
作业必须全部装入内存才能运行,大作业无法运行
-
多道程序并发度下降
基于著名局部性原理
-
时间局部性
程序存在大量循环
- 空间局部性
数据连续存放同一个程序的数据可能在一个页表项里面
虚拟内存技术基于离散分配的内存管理方式
虚拟内存的实现就有:
- 请求分页存储管理
- 请求分段存储管理
- 请求段页式存储管理
主要区别:
操作系统负责请求调页、和页面置换功能,就是把需要的页面在内存外存之间交换
13-请求分页管理方式(虚拟内存)
13.1 页表机制
- 为了实现请求调页,需要知道是否调入了内存,没调入的话需要知道页面在外存中存放的位置
- 为了实现页面置换,需要决定应该换出哪个页面,
- 有的页面没修改过就直接删掉不用写回外存,有的页面修改过需要写回外存覆盖原信息,
- 所以操作系统还需要记录各个页面是否被修改的信息
本来的页表只有内存块号,现在又增加了
- 【状态位】是否已经调入内存
- 【访问字段】记录最近被访问过几次或者上次访问的时间——用于页面置换算法
- 【修改位】是否修改过
- 【外存地址】调入时的外存地址方便回写
13.2缺页中断机构
生效时机,慢表中找到页面时查看是否在内存中
- 访问的页面不在时,产生一个缺页中断,使进程阻塞,进行io
- 内存中有空闲内存块就分配给他,没有就用页面置换算法淘汰一个页面
- 淘汰的页面修改过的话需要重新写回外存
①只有写指令才会修改‘修改位’、一般来说只修改快表中的数据,只有将快表项全部删除时才需要写回内存中的慢表,这样可以减少访存次数
②产生缺页中断的时候要把进程阻塞进入阻塞
③从外存调入内存慢表中的同时也会在快表中增加他
14-页面置换算法
- 最佳置换OPT
- 预先知道所有页面请求情况,每次决定换入换出的时候选择最长时间不会被访问的页面
- 先进先出FIFO
- 队列 —— 谁先来现走
- 最近最久未使用LRU
- 还是队列,但是如果再次命中会刷新他的排位
- 时钟置换算法CLOCK
- 访问位:通过循环队列,每次扫描一遍,遇到一就置零然后过,遇到零就换出,命中了的话就置一
- 改进型时钟置换
- 思想:需要把那些没有修改过的优先换出,效率会更高
- 为了方便接下来把页面表示为(访问位,修改位)
- 进行两轮扫描,
- 第一轮扫描试图找到 (0,0) 的页面换出
- 第二轮扫描试图找到 (0,1) 的页面换出 这轮把扫描通过了的的(1,1)和(1,0)的访问位设置为0,
- 第三轮扫描试图找到 (0,0) 的页面换出 来自于上一轮的被改了访问位的(1,0)
- 第四轮扫描试图找到 (0,1) 的页面换出 来自于第二轮被改了访问位的(1,1)
15-页面分配策略
15.1 驻留集
概念、指的是分页存储管理中给进程分配的内存块的集合。
驻留集非常明显的影响缺页率,比如驻留集和进程一样大就没有缺页
固定分配为每个进程分配一组固定数目的物理块(内存块),在进程运行期间,也不变,驻留集大小不变
可变分配:为每个进程分配一定数目的物理块(内存块),在晋城运行期间,可根据情况做适当的增加或减少,即驻留集大小可变
局部置换:发生缺页时只能选进程自己的物理块(内存块)进行置换。
**全局置换:**发生缺页时取用操作系统空闲的内存块或者将别的进程持有的物理块(内存块)置换到外存,再分配给缺页进程
15.1何时调入页面
1.预调页策略:根据局部性原理,一次调入若干个相邻的页面**。这种策略主要用于进程的首次调入,由程序员指出应该先调入哪些部分**
2.请求调页策略:进程**在运行期间发现缺页时才将所缺的页面调入内存。**虽然调入的页面一定会被访问到,但由于每次只能调入一页,而每次调页都要磁盘 I / O 操作,IO开销大
15.2何处调入页面
外存有对换区和文件区
对换区采用连续分配方式读写更快::::文件区采用 离散分配方式
- 进程运行前需要将进程相关的数据从文件区复制到对换区
- 系统要是对换区空间不够的话 把不会修改(之后修改了不用再回写)的数据从文件区调入,
- UNIX方式:页面没有被使用过,从文件区直接调入内存,如果内存空间不够的时候,换出到对换区
15.3抖动(颠簸)现象
刚刚换出的页面马上又换入内存,刚刚换入的页面马上又要换出外存,
主要原因:进程频繁访问的页面数高于可用的物理块数,(分配给进程的物理块数不够)
所以要为进程合适的物理块
15.4工作集
概念:某段时间进程实际访问的页面的集合。
操作系统会根据【窗口尺寸】来算出工作集
系统可以检测工作集的大小来决定给进程分配多少内存块(驻留集的大小)
(相关拓展)页面置换算法:不在工作集中的页面优秀调出

6915

被折叠的 条评论
为什么被折叠?



