前言
自己学习计算机操作系统时总结的一些知识点
内存管理
基础知识
程序执行前需要先放到内存中才能被CPU处理——缓和CPU与硬盘之间的速度矛盾
常用数量单位:
2^10 = 1K 2^20=1M 2^30=1G
逻辑地址=相对地址 物理地址=绝对地址
指令:操作码 + 若干参数
内部碎片:分配给某进程的内存区域中,某些部分没有用上
外部碎片:指内存中的某些空闲分区由于太小而难以利用
程序运行:
- 编译:由源代码文件生成目标模块
- 链接:由目标模块生成装入模块,连接后形成完整的逻辑地址
- 装入:将装入模块装入内存,形成物理地址
装入的三种方式:
- 绝对装入:编译、链接后得到的装入模块的指令直接就使用了绝对地址(灵活性低)
- 静态重定位:是在装入内存时根据内存的当前情况,将装入模块装入到 内存的适当位置。
- 动态重定位:装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是把地址转换推迟到程序真正要执行时才进行。装入内存后的所有地址依然是逻辑地址,并且需要一个重定位寄存器来支持(重定位寄存器存放装入模块的起始地址)
链接的三种方式:
- 静态链接:装入前链接成一个完整装入模块
- 装入时动态链接:运行前边装入边链接
- 运行时装入链接:运行时需要目标模块时才装入并链接
内存空间的分配与回收
操作系统对内存进行管理的方面:
-
内存空间的分配与回收
-
连续分配管理方式:为用户进程分配的必须是一个连续的内存空间
-
单一连续分配:内存被分为系统区和用户区
- 系统区:在内存低地址部分,存放操作系统相关数据
- 用户区:存放用户进程相关数据
- 内存中只能有一道用户程序,用户程序独占整个用户区空间,因此无外部碎片,但存储器利用率极低,有内部碎片。
-
固定分区分配:将整个用户空间划分为若干个固定大小的分区,在每个分区中只可以装入一道作业。
-
分区大小相等:适合用于一台计算机控制多个相同对象的场合
-
分区大小不等:灵活性好,可以满足不同大小的进程
-
操作系统需要建立一个数据结构——分区说明表,实现各个分区的分配与回收
- 无外部碎片,有内部碎片
-
-
动态分区分配:不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态地建立分区
-
空闲分区表
-
空闲分区链
-
无内部碎片,有外部碎片
-
-
-
非连续分配管理方式:分配的内存空间可以离散的
-
基本分页存储管理
分页存储:将内存空间分为一个个大小相等的分区,每个分区就是一个页框,页框号从0开始。
将进程的逻辑地址空间也分为与页框大小相等的一个个部分,每个部分称“页面”,页面号也从0开始。
操作系统以页框为单位为各个进程分配内存空间,进程的每个页面分别放入一个页框中,即页面与页框一一对应。
由上可以知道,页面可以不连续存放在不相邻的各个页框中。
页表:为了能够知道进程的每个页面在内存中存放的位置,操作系统要为每个进程建立一张页表(页表存放在内存中,只有页块占用存储空间,页号是隐含的,相当于数组的下标)。
同时,每个进程对应一张页表,进程的每个页面对应一个页表项(由页号和块号组成,每个页表项的长度是相同的),页表记录进程页面和实际存放的内存块之间的映射关系。
如何确定一个逻辑地址对应的页号、页内偏移量?
页号 = 逻辑地址 / 页面长度
页内偏移量 = 逻辑地址 % 页面长度
根据页号得到块号在内存中的起始地址 + 页内偏移量 = 实际物理地址
结论:如果每个页面大小为2^k 字节,用二进制数来表示逻辑地址时,则末尾k位位业内偏移量,其余部分为页号。
基本地址变换机构(过程):
两次访问内存:一次是查页表,另外一次是访问目标内存单元
具有快表的地址变换机构:
快表:TLB,一种访问速度比内存块很多的高速缓存(不是内存!),用来存放最近访问的页表项的副本,可加速地址变换的速度。
慢表:与快表对应,内存(RAM)中的页表。
-
基本分段存储管理
进程的地址空间:按照程序自身的逻辑关系划分为若干个段,每个段都有一个段名,没断从0开始编址。
分段系统的逻辑地址结构由**段号(段名)和段内地址(段内偏移量)**所组成,如下:
其中,编译程序会把段名(如上D,X)转换为段号,会将单元(如上A,B)翻译成段内地址
段表:一个程序分为多个段,每个段离散装入内存,段表就是为了能够从物理内存中找到各个逻辑段的存放位置。
分段存储管理过程:
分段、分页管理对比:
页是信息的物理单位,对用户不可见;段是信息的逻辑单位,对用户可见。
页的大小固定且由系统决定;段的长度不固定,由用户编写的程序决定
分页的用户进程地址空间是一维的;分段的用户进程地址空间是二维的
-
段页式存储管理
结合分段和分页式管理的存储管理方式
段页式系统的逻辑地址结构由段号、页号、页内地址(业内偏移量)组成——>因此地址结构是二维的。
段页式管理中的段表存放的是页表长度和页表存放块号
段页式管理过程:
-
-
-
内存空间的扩充:虚拟性 比如玩 GTA游戏16G 但是内存只有4G,用到了虚拟技术)
-
覆盖技术:用来解决“程序大小超过物理内存总和”的问题
- 核心思想:将程序分成多个段,常用的常驻内存(固定区),不常用的需要时才调入内存(覆盖区)。
- 示例:
-
交换技术: 注意:PCB会常驻内存
- 核心思想:内存空间紧张时,系统将内存中某些进程暂时唤出外存(变为挂起状态),把外存中某些已经具备运行条件的进程换入内存。
- 被唤出的进程应该保存在什么位置?
- 对于具有交换功能的操作系统中,通常把磁盘空间分为文件区和对换区。对换区的I/O速度大于文件区
- 文件区:主要用于存放文件,空间管理方式为离散分配方式。追求存储空间的利用率
- 对换区:存放被出的进程数据,通常采用连续分配方式用于追求换入换出速度。
- 什么时候交换?
- 通常在许多进程运行且内存吃紧时进行
- 应该唤出哪些进行?
- 阻塞态进程
- 优先级低的进程
-
虚拟存储技术
-
-
地址转换:负责实现逻辑地址到物理地址的转换
-
存储保护:保护进程在自己的内存空间内运行,不会越界访问
- 设置上下界寄存器
- 利用重定位寄存器(存放进程的起始物理地址)、界地址寄存器(进程的最大逻辑地址)进行判断
动态分区分配算法:
- 首次适应算法:每次从低地址开始查找,找到第一个能满足大小的空闲分区。
- 最佳适应算法:优先使用小的连续空闲区,留下大的空闲区。缺点:会产生很多的外部碎片
- 最坏适应算法:优先使用大的连续空闲区。缺点:优先使用大空闲区,可能后续大进程无法使用。
- 邻近适应算法:每次都从上次查找结束的位置开始检索。
单级页表的问题:
-
页表必须连续存放,因此当页表很大时,需要占用很多个连续的页框
解决方法:
采用两级页表
-
没有必要让整个页表常驻内存,因为进程在一段时间内可能只需要访问几个特定的页面
解决方法:可以在需要访问页面时才把页面调入内存,在页表项中增加一个标志位,用于表示该页面是否已经调入内存。
在采用多级页表机制是,各级页表的大小不能超过一个页面
N级页表访问一个逻辑地址需要访问 N+1 次内存
虚拟内存
传统存储管理方式的特征和缺点:
- 一次性:作业数据必须一次全部调入内存
- 驻留性:作业数据在整个运行期间都会常驻内存
局部性原理:
- 时间局部性:当前访问的指令、数据在不久后很可能会被再次访问
- 空间局部性:现在访问的内存单元周围的内存空间,很可能在不久之后被访问
高速缓存技术:使用频繁的数据放到更高速的存储器中
虚拟内存基本概念
-
定义:程序不需要全部装入即可运行,运行时根据需要动态调入数据,若内存不够,还需换出一些数据。
-
特征:
- 多次性:无需在作业运行时一次性全部装入内存,而是允许被分成多次调入内存
- 对换性:无需在作业时一直常驻内存,而是允许在作业运行过程中,将作业换入唤出
- 虚拟性:逻辑上扩充了内存的容量,使用户看到的内存容量,远大于实际容量
-
如何实现:
- 请求调页:访问的信息不存在于内存中时,由操作系统负责将所需信息从外村调入内存
- 页面置换:内存空间不够时,将内存中暂时用不到的信息唤出到外村
-
实现方式:
-
请求分页存储管理
-
页表机制(请求页表)
- 状态位:判断是否已经调入内存
- 访问字段:可以记录最近访问次数,供置换算法选择换出页面时参考
- 修改位:页面调入内存后是否被修改过
- 外村地址:页面在外存中存放的位置
-
缺页中断机构(属于“内终端”的故障,可被系统修复)
- 缺页中断是在找到页表项后检查页面是否已在内存,若不在内存,产生缺页中断
- 缺页中断处理:将目标页面调入内存,有必要时还要换出页面
-
地址变换机构
- 找到页表项时需要检查页面是否在内存中
- 若不在内存中,则需要请求调页
- 若内存空间不够,需要唤出页面
- 页面调入内存后,需要修改相应页表项
流程图:
-
-
请求分段存储管理
-
请求段页式存储管理
-
页面置换算法:
-
最佳置换算法OPT:每次选择淘汰的页面将是以后永不使用,或者在最长时间内不再被访问的页面。可以保证最低的缺页率,但在实际使用中无法实现,因为需要"预知"
-
先进先出置换算法FIFO:每次淘汰的页面是最早进入内存的页面,队列的最大长度取决于系统为进程分配了多少个内存块。缺点:可能会出现Belady异常——当为进程分配的物理块数增大时,缺页次数不减反增的异常现象。
-
最近最久未使用置换算法LRU:每次淘汰的页面是最近最久未使用的页面(利用页表项的访问字段)缺点:需要专门的硬件支持
-
时钟置换算法(最近未用算法)CLOCK:
- 简单CLOCK算法:
-
改进型CLOCK算法:(其他条件都相同时,优先淘汰没有修改的页面,避免IO操作)
页面分配策略:
- 驻留集:指的是请求分页存储中给进程分配的内存块的集合
- 工作集:某段时间间隔里,进程实际访问页面的集合,驻留集大小一般不能小于工作集大小
- 页面分配、置换策略:
- 固定分配 vs 可变分配:区别在于进程运行期间驻留集大小是否可变
- 局部置换 vs 全局置换:区别在于发生缺页时是否只能从进程自己的页面中选择一个唤出
- 固定分配局部置换:进程运行前就分配一定数量的物理块,缺页时只换出进程自己的某一页
- 可变分配全局置换:只要缺页就分配新的物理块,可能来自空闲物理块,也可能需换出别的进程的页面
- 可变分配局部置换:频繁缺页的进程多分配一些物理块;缺页率很低的进程,回收一些物理块,知道缺页率合适
- 何时调入页面:
- 预调页策略:一般用于进程运行前
- 请求调页策略:进程运行时,发现缺页再调页
- 从何处调页(对换区——连续存储方式,速度快;文件区——离散存储方式,速度慢)
- 对换区足够大:运行将数据从文件区复制到对换区,之后所有页面调入、调出都是再内存与交换区之间进行
- 对换区不够大:不会修改的数据每次都从文件区调入;会修改的数据调出到对换区,需要时从对换区调入
- UNIX方式:第一次使用的页面都从文件区调入;调出的页面都写回对换区,再次使用时从对换区调入
- 抖动现象:页面频繁换入换出的现象,主要原因为分配给进程的物理块不够