操作系统整理
文章目录
1.操作系统概述
1.1操作系统的基本特征
并发和共享是操作系统的两个最基本特征
- 并发:并发是指两个或多个事件在同一时间间隔内发生
- 共享:系统中的资源可供内存中多个并发执行的进程共同使用
- 虚拟:把一个物理上的实体变成若干逻辑上的对应物
- 异步:多道程序环境允许多个程序并发执行。进程的执行并不是一贯到底的,而是走走停停以不可预知的速度前进。
1.2操作系统的基本功能
- 操作系统作为计算机系统资源的管理者
- 处理机管理
- 存储器管理
- 文件管理
- 设备管理
- 操作系统作为用户与计算机硬件系统之间的接口
- 命令接口
- 联机命令接口
- 脱机命令接口
- 程序接口
- 系统调用
- GUI
- 命令接口
- 操作系统用作扩充机器
2.进程管理
2.1进程与线程(重要)
-
调度的基本单位
- 传统的OS中,进程是作为独立调度和分派的基本单位
- 引入线程的OS中,线程是作为调度和分派的基本单位,因而线程是能独立运行的基本单位
-
并发性
- 引入线程的OS中,不仅进程之间可以并发执行,而且在一个进程中的多个线程之间亦可并发执行。
-
拥有资源
- 进程可以拥有资源,并作为系统中拥有资源的一个基本单位
- 线程本身不拥有系统资源,而是仅有一点必不可少的能保证独立运行的资源
-
独立性
- 同一进程中的不同线程共享进程的内存地址和资源
- 每个进程都拥有一个独立的进程空间和其他资源
-
系统开销
- 在创建或撤销进程时,OS为此付出的开销,明显大于线程创建或撤销所付出的开销
-
支持多处理机系统
- 传统的单线程进程只能运行在一个处理机上,多线程进程可以将一个进程中的多个线程分配到多个处理机上并行执行
2.1.4进程的组成
简略版本
进程描述信息 | 进程控制和管理信息 | 资源分配清单 | 处理机相关信息 |
---|---|---|---|
PID | 处理机占用时间 | 文件描述符 | 通用、地址、控制、标志寄存器 |
UID | 进入内存时间 | 状态字 |
2.1.5进程的通信
- 共享存储
- 低级方式:基于数据结构的共享
- 高级方式:基于存储区的共享
- 消息传递:
- 直接通信方式:发送进程直接把消息发送给接收进程,并把它挂在接收进程的消息缓冲队列上
- 间接通信方式:发送进程把消息发送到中间某个实体,接收进程从中间实体获得消息。(该实体叫信箱)
- 管道通信:
- 管道采用半双工通信,某一时刻只能单向传输。
- 实际上,管道是一个固定大小的缓冲区。
2.2处理机调度
2.2.4调度的基本准则
- CPU利用率: 利 用 率 = c p u 忙 的 时 间 进 程 总 时 间 利用率=\frac{cpu忙的时间}{进程总时间} 利用率=进程总时间cpu忙的时间
- 周转时间: 作 业 完 成 时 间 − 作 业 提 交 时 间 作业完成时间-作业提交时间 作业完成时间−作业提交时间
- 平均周转时间:$\frac{Σ作业_{i}的周转时间}n $
- 等待时间: 进 程 处 于 等 处 理 机 状 态 的 时 间 之 和 进程处于等处理机状态的时间之和 进程处于等处理机状态的时间之和,一般使用 进 程 周 转 时 间 − c p u 运 行 时 间 进程周转时间-cpu运行时间 进程周转时间−cpu运行时间[在IO时候也是被服务的]
- 带权周转时间: 作 业 周 转 时 间 作 业 实 际 运 行 时 间 \frac{作业周转时间}{作业实际运行时间} 作业实际运行时间作业周转时间
- 平均带权周转时间: Σ 作 业 i 的 带 权 周 转 时 间 n \frac{Σ作业_{i}的带权周转时间}{n} nΣ作业i的带权周转时间
- 响 应 比 = 等 待 时 间 + 要 求 服 务 时 间 要 求 服 务 时 间 响应比=\frac{等待时间+要求服务时间}{要求服务时间} 响应比=要求服务时间等待时间+要求服务时间
2.2.5典型的调度算法
2.2.5.1调度算法
- FCFS(先来先服务)
- SJF(短作业优先)
- 优先级调度
- 高响应比优先调度
响 应 比 = 等 待 时 间 + 要 求 服 务 时 间 要 求 服 务 时 间 响应比=\frac{等待时间+要求服务时间}{要求服务时间} 响应比=要求服务时间等待时间+要求服务时间
- 时间片轮转调度
按照时间配额来运行的,时间一到不管是否完成,当前进程必须撤下换新的进程,因此是由时间配额决定的,是绝对可抢占的。
- 多级反馈队列调度算法
优先级从上到下依次降低,分配的时间片从上到下依次增加。
特点:
- 对于终端型用户,由于大多提交的是交互型作业,作业通常短小,属于短作业优先。
- 对于短批处理作业用户来说,若仅在第一级队列完成则可以获得与终端型作业一样的响应时间,稍长的通常在第二级和第三级中各执行一个时间片即可完成
- 对于长批处理作业用户来说,其长作业依次在各队列中运行,然后再按时间片轮转的方式运行,用户不必担心其作业长期得不到处理。
2.2.5.2甘特图画法注意事项
- 给每个进程标记下一步处理的事项
- 依次按照甘特图上的每一个阶段的结束来按照调度算法分配规则看进程顺序来进行下一步的分配
- 甘特图的纵坐标按编号顺序排列更不容易乱
2.2.5.3调度算法的总结
做题的时候要注意默认抢占与否
先来先服务 | 短作业优先 | 高响应比优先 | 时间片轮转 | 多级反馈队列 | |
---|---|---|---|---|---|
能否是可抢占 | 否 | 能 | 能 | 能 | 队列内算法不一定 |
能否是不可抢占 | 能 | 能 | 能 | 否 | 队列内算法不一定 |
优点 | 公平,实现简单 | 平均等待时间最少,效率最高 | 兼顾长短作业 | 兼顾长短作业 | 兼顾长短作业,有较好的响应时间,可行性强 |
缺点 | 不利于短作业 | 长作业会饥饿,估计时间不易确定 | 计算响应比的开销大 | 平均等待时间较长,上下文切换浪费时间 | 无 |
适用于 | 无 | 作业调度,批处理系统 | 无 | 分时系统 | 相当通用 |
默认决策模式 | 非抢占 | 非抢占 | 非抢占 | 抢占 | 抢占 |
2.3进程同步
2.3.1概念
临界资源:一次只能为一个进程所用的资源。对临界资源的访问,必须互斥地进行。
**临界资源和共享资源的对比:**临界资源就是如果一个进程对他使用,别的进程只有等该进程,结束后才可以使用。比如打印机。
而共享资源是不管他结束与否,别的进程都可以使用。比如cpu,磁盘介质(并发IO的概念)
进入区:检查可否进入临界区使用临界资源。
临界区:进程访问临界资源的代码
退出区:将正在访问临界区的标志清除
剩余区:代码中的其余部分
同步(直接制约关系):多个进程因为需要在某些位置上协调它们的工作次序而等待、传递信息所产生的制约关系。
互斥(间接制约关系):当一个进程进入到临界区使用临界资源时,另一进程必须等待,当占用临界资源的进程退出临界区后,另一进程才去访问此临界资源。
互斥的四个原则:①空闲让进②忙则等待③有限等待④让权等待
管程:代表共享资源的数据结构以及由对该共享数据结构实施操作的一组过程所组成的资源管理程序,称为管程。管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作。
可重入编码:“可重入代码又称为“纯代码”,是一种允许多个进程访问的代码,因此,可重入代码是一种不允许任何进程对它进行修改的代码
2.3.3信号量
整形信号量未遵循"让权等待"的原则。
记录形信号量遵循了让权等待的原则。
注意当下S.value<0的时候该进程阻塞。
void wait(semaphore S){
S.value--;
if(S.value<0){
add this process to S.L;
block(S.L);
}
}
当value值仍然<=0说明仍有进程阻塞中,此时可以唤醒。
void signal(semaphore S)
{
S.value++;
if(S.value<=0)
{
remove a process P from S.L;
wakeup(P);
}
}
2.3.4管程
monitor Demo{/*①定义一个名称为'Demo'的管程*/
//②定义共享数据结构,对应于系统中的某种共享资源
共享数据结构S;
//④对共享数据结构初始化的语句
init_code(){S=5;}
//③过程1:申请一个资源
take_away(){
...
}
//③过程2:归还一个资源
give_back(){
S++;
...
}
}
管程的组成部分:
- 管程的名称
- 局部于管程内部的共享数据结构说明
- 对该数据结构进行操作的一组过程(或函数)
- 对局部于管程内部的共享数据设置初始值的语句
特点:
- 管程把对共享资源的操作封装起来
- 每次仅允许一个进程进入管程,从而实现进程互斥
条件变量:
x.wait
:当x对应的条件不满足时,调用此函数将自己插入x
条件的等待队列并释放管程,此时其他进程可以使用该管程x.signal
:x对应的条件发生了变化,调用则唤醒一个因x
条件而阻塞的进程。
monitor Demo{/*①定义一个名称为'Demo'的管程*/
//②定义共享数据结构,对应于系统中的某种共享资源
共享数据结构S;
//④对共享数据结构初始化的语句
init_code(){S=5;}
//③过程1:申请一个资源
take_away(){
if(S<=0) x.wait();
//资源足够,分配资源,做一系列处理
}
give_back(){
//归还资源,做一系列处理
if(有进程在等待) x.signal;
}
}
2.3.5经典同步问题
2.3.5.1做题步骤
- 常用小口诀
- 画图理解题目
- 判断题目类型
- 分析进程数目,填写进程模板
- 补充基本代码(伪代码)
- 补充P,V代码
- 检查调整代码
代码是一步一步写出来的,反复调试写出来的
写题的时候注意:
- 对象个数的注意,一个和多个是不一样的,比如一个服务员和多个服务员。多个服务员是能通过当前的取号和叫号进行并发叫号的,在判断的
if
逻辑中就可以释放叫号锁然后开始服务;而一个服务员要服务完才能释放叫号锁。 - 有的题对缓冲池满后有额外的逻辑,是等待还是离开是要注意的。
- 关键还是对同步的把握,比如有了顾客取号服务员才会被唤醒,有了服务员叫号等待的顾客才会被唤醒。这里是两个同步关系,采用两个变量设置。如此慢慢分析写题的时候更不容易漏掉东西。
- 当一个服务员唤醒顾客的时候就可以紧跟着释放座位更加符合实际。
- 最后写的时候要检查进程是否锁得住。
2.3.5.1生产者消费者模型
-
重要的一点就是对于容量这个属性来说,一般直接定义两个用于两个对象描述该属性的变量。互相一加一减(经典就是full和empty)。
-
若容量属性需要满足条件是不等式条件,将变式整体看成一个变量定义,不等式右边看成一个总量。如此总量就相当于空闲区数量或者已有的数量了。
-
当出现每次获取资源数目不等的时候就要考虑到可能产生死锁。
- 拆除死锁条件:规定每个资源所能生产的最大数目
- 取资源的时候可以考虑一个个取或者条件全部满足再取。前者一个个取更能体现同步关系。
2.3.5.2读者写者问题
- 对于可能导致饥饿的两边公平的读写者问题,对临界资源在封锁数目计数的时候判断为空进行锁掉临界资源或者释放掉临界资源
2.3.5.3哲学家问题
书上的一个做法是每次能保证一次能拿满资源的哲学家拿,先拿左再拿右,并且限制拿全部资源的整个过程。这样总能保证有一个哲学家能吃东西,之后也可以解除另外一个人的阻塞。
2.4注意事项
- 如果当前使用的是
while
来实现模拟阻塞
的多线程,唤醒的是就绪态的进程。该进程不会阻塞因为没有block
2.4死锁
2.4.1死锁的定义
多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。
2.4.2死锁产生的原因
- 系统资源的竞争
- 进程推进顺序非法
- 死锁产生的必要条件
- 互斥条件
- 进程对资源的访问允许进程在一段时间内为进程所有
- 不剥夺条件
- 进程已申请的资源在未使用完成前不能被其他进程剥夺
- 请求并保持条件
- 进程在已经获得资源的情况下提出对资源新的请求陷入阻塞但仍然保持已获得的资源
- 循环等待条件
- 存在一种进程资源的等待循环链,每个进程已经获得的资源被链中下一个进程请求
- 互斥条件
Tips:带环图不一定死锁,死锁一定带环
2.4.3死锁的处理策略
2.4.3.1死锁预防(静态策略)
- 破环互斥条件
- 不太现实
- 破坏不剥夺条件
- 当一个已保持了某些不可剥夺资源的进程请求新的资源而得不到满足的时候,它必须释放已经保持的所有资源,待以后需要时再重新分配
- 破坏请求并保持条件
- 预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前不投入运行
- 破坏循环等待条件
- 顺序资源分配法,给系统中的资源编号,规定每个进程必须按编号递增的顺序请求资源,同类资源一次申请完
2.4.3.2死锁避免(动态策略——银行家算法)
银行家算法过程:
- 求出Need矩阵
- 对于当前请求分配资源的进程,先假设分配并求出分配后的结果。
- 寻找剩下是否存在一种方式能把资源全部回收回来(实际上贪心地从要求资源最少的进程开始分配后回收资源即可)。若存在就分配,若不存在说明系统此时不安全,即不分配资源给当前申请进程。
2.4.3.3死锁的检测
-
资源分配图
- 进程对资源的请求边表示进程还需要;资源对进程的有向边表示进程已经有的资源
-
死锁定理
- 依次清除与不阻塞进程相连的边,直到无边可消。如果该资源分配图不可完全简化则是死锁
2.4.3.2死锁的解除
- 资源剥夺法
- 挂起某些死锁进程并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源而处于匮乏的状态
- 撤销进程法
- 强制撤销部分甚至全部死锁进程并剥夺这些进程的资源。撤销的原则可以按进程的优先级和撤销进程代价的高低进行。
- 进程回退法
- 让一(或多)进程回退到足以回避死锁的地步,进程回退时自愿释放资源而非被剥夺。要求系统保持进程的历史信息,设置还原点。
2.4.3.3死锁处理方法的并发性排序
忽略,检测与恢复,避免和预防。
对死锁的处理从宽到严,同时系统的并发性从大到小。
3.内存管理
传统存储管理方式(虚拟内存管理之前),其内存策略有以下特征:
- 一次性:作业必须一次性装入内存后,才能开始运行
- 导致当前作业会因为很大不能全部装入内存,导致该作业无法运行
- 大量作业要求运行的时候由于内存不足不足以容纳所有作业因此只能选择一定的作业调度方式,导致多道程序度下降
- 驻留性:作业被装入内存后,就一直驻留在内存中,其任何部分都不会被换出,直至作业运行结束。
以下先学习传统存储管理
3.1内存管理的概念
3.1.1内存管理的功能
- 内存空间的分配和回收
- 由操作系统完成主存储器空间的分配和管理,使程序员摆脱存储分配的麻烦
- 地址转换
- 多道程序环境下,程序中的逻辑地址与内存中的物理地址不可能一致,因此存储管理必须提供地址变换功能。
- 内存空间的扩充
- 利用虚拟存储技术或自动覆盖技术,从逻辑上扩充内存。
- 存储保护
- 保证各道作业在各自的存储空间中运行,互不干扰。
3.1.2程序的链接方式和装入方式
预处理-编译-汇编-链接
程序的链接方式:
- 静态链接:程序运行前将各个目标模块和所需要的库函数链接成一个完成的二进制可执行程序
- 动态链接:
- 装入时动态链接:目标模块在装入内存时,边装入边链接
- 这种用法的前提是在编译之前已经明确知道要调用DLL中的哪几个函数,编译时在目标文件中只保留必要的链接信息,而不含DLL函数的代码;当程序执行时,利用链接信息加载DLL函数代码并在内存中将其链接入调用程序的执行空间中,其主要目的是便于代码共享。
- 运行时动态链接:程序在执行过程中需要该目标模块时才进行的
- 这种方式是指在编译之前并不知道将会调用哪些DLL函数,完全是在运行过程中根据需要决定应调用哪个函数,并用LoadLibrary和GetProcAddress态获得DLL函数的入口地址。
- 装入时动态链接:目标模块在装入内存时,边装入边链接
程序的装入方式:
- 绝对装入:知道程序将驻留在内存的某个位置,则编译程序将产生绝对地址的目标代码
- 可重定位装入(又称静态重定位):根据内存的情况,将装入模块装入到内存的适当位置,装入时对地址重定位(对目标程序中指令和数据的修改)。
- 一个作业装入内存时,必须分配要求的全部内存空间。
- 作业一旦进入内存后整个运行期间就不能再在内存中移动和申请内存空间了。
- 要求连续分配
- 动态重定位:装入模块中的相对地址转换推迟到程序真正运行时才产生。
- 可以将程序分配到不连续的存储区中,程序运行期间根据动态申请分配内存。
- 由于推迟到程序真正运行时才产生因此装入内存的时候程序里面仍然是逻辑地址
Tips:
- 预处理编译产生的程序的逻辑地址都是从0开始的
- 链接完各个二进制可执行文件组合在一起变成一个完整的逻辑地址程序
- 至于物理地址的分配要看程序的装入方式
- 动态链接是指在作业运行之前,并不把几个目标程序段链接起来。要运行时,先将主程序所对应的目标程序装入内存并启动运行,当运行过程中又需要调用某段时,才将该段(目标程序)调入内存并进行链接。可见,动态链接也要求以段作为管理的单位
3.1.3交换(对换)
- 内存中某些进程被阻塞,却占用内存空间;
- 外存上有许多作业在等,因无法进入内存运行。
"占着不用"是浪费,使系统吞吐量下降。为解决此问题,系统增设对换(交换)设施。
交换的对象是两个进程。
Tips:
- 使用交换技术的时候进程正在I/O的时候不能交换出主存
3.2内存分配的方式
内部碎片:分配给某进程的内存区域中,没有用上的部分
外部碎片:内存中的某些空闲分区由于太小难以利用。注意外部碎片需要Σ外部空间的容量>=申请的容量,这些空闲分区才能称之为外部碎片。
3.2.1连续分配方式
3.2.1.1单一连续分配
适用范围:单用户单任务的操作系统
内存分为系统区和用户区,内存中永远只有一道程序,无需进行内存保护。
3.2.1.2固定分区分配
固定分区分配在划分分区时有两种不同的方法:
- 分区大小相等
- 分区大小不等:划分为多个较小的分区,适量的中等分区和少量大分区
通常按照分区大小排队,建立分区说明表。
3.2.1.3动态分区分配(可变分区分配)
不预先划分内存,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要
理解的话就是oslab3,最佳适应算法的处理。
注意动态连续分配会产生外部内存碎片,因此操作系统时不时会使用紧凑技术,即移动进程的位置
3.2.1.3.1动态分区算法
- 首次适应算法(First Fit)。按照地址的递增次序链接
- 最简单最好最快
- 低地址部分会出现很多的内存分区
- 最佳适应算法(Best Fit)。按照空间的容量递增方式
- 性能最差,产生最多的外部碎片
- 最坏适应算法(Worst Fit)。又称最大适应算法。以空间容量递减顺序方式
- 会导致没有可用的大内存块
- 邻近适应(Next Fit)。循环首次适应算法,分配内存从上次查找结束的位置开始继续查找。
3.2.2非连续分配管理方式(重点)
3.2.2.1基本分页存储管理方式
- 基本概念
分页:把主存空间划分为大小相等且固定的块,块相对较小,作为主存的基本单位。每个进程也以块为单元进行划分,进程在执行时,以块为单元申请主存中的块空间。
对于逻辑空间来说:页=页面;==>页号=页面号
对于页表来说:页表项中存储的是块号
对于内存来说:页框,页帧,物理块,物理页面。其中的编号是页框号
快表,又称TLB(相联存储器),用来存放当前访问的若干页表项,以加速地址变换的过程
- 重要关系
内存块大小=页面大小
页面大小:一个页面占多大空间( 2 页 内 偏 移 量 的 位 数 2^{页内偏移量的位数} 2页内偏移量的位数)
页表项长度:每个页表项占多大存储空间( ⌈ 页 号 位 数 8 ⌉ \lceil \frac{页号位数}{8} \rceil ⌈8页号位数⌉)
页表长度:页表中有多少个页表项( 页 表 长 度 = 进 程 地 址 空 间 页 面 大 小 页表长度=\frac{进程地址空间}{页面大小} 页表长度=页面大小进程地址空间)
页表大小:页表项长度*页表长度
计算机中内存块的数量=页表长度
i号内存块的地址=i*内存块的大小
页号是由进程的逻辑地址给的。
- 一级页表逻辑结构
页号 | 内存块 |
---|
- 二级页表逻辑地址结构
一级页号 | 二级页号 | 页内偏移 |
---|
特别地,对于多级分页来说:各级页表的大小不能超过一个页面。
所以可以通过一个页面大小÷页表项长度获得二级页表长度
一 级 页 目 录 表 包 含 的 表 项 个 数 = 二 级 页 表 页 面 长 度 = 一 个 物 理 块 大 小 页 表 项 长 度 一级页目录表包含的表项个数=二级页表页面长度=\frac{一个物理块大小}{页表项长度} 一级页目录表包含的表项个数=二级页表页面长度=页表项长度一个物理块大小
- 带有快表的一级页表
注意快表是寄存器(TLB——相联寄存器),其访问速度不是按照访问内存的时间来计算的。
3.2.2.2基本分段存储管理方式
段式存储方式需要存储段号和段内偏移量,所以是二维的。
-
基本概念
段式管理方式按照用户进程中的自然段划分逻辑空间。段号和段内偏移量必须由用户显示提供。
-
引入
- 方便编程
- 信息共享
- 信息保护
- 动态增长
- 动态链接
-
逻辑地址结构
段号S | 段内偏移量W |
---|
段表的内容
段长 | 基址 |
---|
- 寻找的过程
由逻辑地址结构取出段号S,比较段号S和段表长度M。由于段表项大小固定,S对应的段表项地址=段表初始地址F+S*段表项长度,判断M是否和段长C越界;取出该段初始地址b,实际物理地址E=b+W访问物理内存。
3.2.2.3段页式存储管理方式
- 逻辑地址
段号S | 页号P | 页内偏移量W |
---|
3.2.3总结与对比
- 分段和分页的区别
- 页是信息的物理单位。段是信息的逻辑单位
- 页的大小固定且由系统决定,段的长度不固定,决定于用户所编写的程序
- 分页的用户程序地址通常是一维的,分段的用户程序地址是二维的。
- 分页是一维的,分段是二维的,段页是二维的
分页的时候逻辑地址自动生成,os自动解析,因为物理块大小一样,所以可以直接算出来块号找到对应的物理块号再加偏移。
但是分段的时候逻辑地址虽然自动生成,但是段长是不定的。就像之前写汇编代码一样需要规定这一段的程序在哪个段里,这个段有多长。(段内的地址是连续自动生成的)os才能找到这个段在段表中对应的段号,在段表中找到实际物理内存地址,然后结合偏移地址。
- 页表和段表都是存在内存中的,页表始址是存在页表基址寄存器(PTBR)中。页表和段表的长度不定,提供给用户的物理地址空间不确定。
- 进程未执行时,页表的始址和页表长度存放在该进程的PCB中,当调度到某进程时,才将这两个数据装入页表寄存器中。
3.3虚拟内存(内存”扩容“技术)
3.3.1虚拟内存的基本概念
传统存储管理方式(虚拟内存管理之前),其内存策略有以下特征:
- 一次性:作业必须一次性装入内存后,才能开始运行
- 导致当前作业会因为很大不能全部装入内存,导致该作业无法运行
- 大量作业要求运行的时候由于内存不足不足以容纳所有作业因此只能选择一定的作业调度方式,导致多道程序度下降
- 驻留性:作业被装入内存后,就一直驻留在内存中,其任何部分都不会被换出,直至作业运行结束。
-
虚拟存储器的定义
- 指具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统。
- 逻辑容量由内存容量和外存容量之和所决定运行速度接近于内存速度,而每位成本却又接近于外存。
-
虚拟内存技术的原理
- 使用外存上的空间来扩充内存空间,通过一定的换入换出,使得整个系统在逻辑上使用一个远远超出其物理内存大小的内存容量
-
局部性原理
- 时间局部性
- 程序中的某条指令一旦执行,不久后可能再次执行;某数据被访问,不久后该数据可能再次被访问。
- 空间局部性
- 一旦程序访问了某个存储单元,不久之后,其附近的存储单元也将被访问。
- 时间局部性
-
虚拟存储器的三大特征
- 多次性:无需在作业运行时一次性地全部装入内存,而允许被多次调度内存运行
- 对换性:对换性是指无须作业运行时一直常驻内存,而允许作业在运行过程中,进行换进和换出
- 虚拟性:从逻辑上扩充内存的容量,使用户所看到的内存容量远大于实际的内存容量
-
虚拟技术的实现
- 请求分页存储管理
- 请求分段存储管理
- 请求段页式存储管理
不管哪种方式都需要硬件的支持:
- 一定容量的内存和外存
- 页表机制(或段表机制),作为主要的数据结构
- 中断机构,当用户程序要访问的部分尚未调入内存时,则产生中断
- 地址变换机构,逻辑地址到物理地址的转换
3.3.2请求分页管理方式
请求分页是目前最常用的一种实现虚拟存储器的方法
- 页表机制
页号 | 物理块号 | 状态位P | 访问字段A | 修改位M | 外存地址 |
---|---|---|---|---|---|
指示该页是否已调入内存 | 用于记录本页在一段时间内被访问的次数 | 标识该位在调入内存后是否被修改过 | 用于指出该页在外村上的地址,通常是物理块号,供调入该页时参考 |
- 缺页中断机构
在请求分页系统中,每当所要访问的页面不在内存中时,便产生一个缺页中断,请求操作系统将所缺的页调入内存。
与一般中断相比两个明显的区别:
- 在指令执行期间而非一条指令执行完后产生和处理中断信号,属于内部中断
- 一条指令在执行期间,可能产生多次缺页中断。
- 地址变换机构
- 虚实地址变换
3.3.3页面置换算法(决定应该换入哪页,换出哪页)
常见的置换算法:
- 最佳置换算法
最佳置换算法选择的被淘汰页面是以后永不使用的页面,或是在最长时间内不再被访问的页面
-
FIFO(先进先出页面置换算法)
- 将当前处于内存中的最早进入的页面给换出
- 存在Belady异常
-
LRU(最近最久未使用置换算法)
过程:从当前在内存的物理块开始,从访问页面往前找到一轮以内在内存中的最前位置的物理块
LRU算法的性能较好,但需要寄存器和栈的硬件支持。
-
clock算法(又称为NRU,NOT RECENTLY USED)
- 简单的clock算法
- 新来的块初始化为1。
- 循环一圈扫描,途中将1的改为0,遇到0的时候停止。
- 改进的clock算法
- 存在访问位A和修改位M。
- 先寻找A=0&&M=0的页面
- 再找A=0&&M=1的页面;如果这次没找到说明这一轮没被访问所以这一次把扫描过的的A都改成0
- 再找A=0&M=0的。(实际上这对应的是A=1&M=0的)没找到将所有的访问位置位0。【不过我没get到这个全部置为0的意义在哪,这应该是在上一步的时候顺带做掉了的】
- 寻找A=0&M=1的(实际上就是A=1&M=1的)
- 存在访问位A和修改位M。
- 简单的clock算法
- 页面缓冲算法
- 影响页面换进换出的因素:
- 页面置换算法:好的页面置换算法,使进程在运行过程中缺页率较低
- 写回磁盘的频率:采用换出一个页面就写回磁盘的策略IO成本太大。建立一个已修改换出页面的链表,对每一个要被换出的页面暂时挂起,到换出页面数量达到一定数量时再写回磁盘
- 读入内存的频率:若已经修改的页面处在链表中,还没写回磁盘。当需要再次访问,能直接访问内存而不用访问磁盘,从而减少磁盘读入频率
- 空闲页面链表:当未被修改的页要换出时,实际上并不将它换出到外存,而是把它所在物理块,挂在空闲链表的末尾。空闲页面链表,不需写回磁盘,装入新页面时,直接覆盖写入
- 修改页面链表:由已修改的页面所形成的链表。已修改页面链表,当链表中的页面数达到一定数目时,集中写回到磁盘上。
- 影响页面换进换出的因素:
3.3.4页面分配策略
3.3.4.1驻留集大小与三种页面分配策略
对于分页式的虚拟内存,在进程准备执行时,不需要也不可能把一个进程的所有页都读入主存。
因此操作系统必须决定读取多少页,即决定给特定的进程分配几个页框。
给一个进程分配的物理页框的集合就是这个进程的驻留集
由此可以推导出:
- 分配一个进程的存储量越少,任何时候驻留在主存中的进程数越多
- 若一个进程在主存中的页数过少,则由于局部性原理,页错误率仍然会相对较高
- 若页数过多,则由于局部性原理,给特定的进程分配更多的主存空间对该进程的错误率没有明显的影响
三种页面分配策略
- 固定分配局部置换
- 为每个进程分配一定数目的物理块,在整个运行期间都不改变
- 这种策略难以确定应为每个进程分配的物理块数目
- 可变分配全局置换
- 最易于实现的物理块分配和置换策略。
- 为系统中的每个进程分配一定数目的物理块;OS自身也保持一个空闲物理块队列。当进程发生缺页时,系统从空闲物理块队列中取出一个物理块分配给该进程,并将欲调入的页装入其中。
- 比固定分配更加灵活,可以动态增加进程的物理块
- 盲目给进程增加物理块会导致多道程序的并发能力下降
- 最易于实现的物理块分配和置换策略。
- 可变分配局部置换
- 为每个进程分配一定数目的物理块,当进程发现缺页时,只允许从该进程在内存的页面中选出一页换出,因此不会影响其他进程的运行。
- 若进程在运行中频繁地缺页,则系统再为该进程分配若干物理块,直至该进程缺页率趋于适当程度
- 反之若进程运行中的缺页率特别低,则可适当分配给该进程的物理块。
- 可以动态增加进程的物理块的数量,还能动态减少进程物理块的数量,在保证进程不会过多调页的同时也保证了多道程序的并发能力。
3.3.4.2调入页面的时机
为确定系统将进程运行时所缺的页面调入内存的时机,可以采用以下两种调页策略:
- 预调页策略(运行前的调入)
- 采用以预测为基础的预调页策略,但是成功率只有50%,因此主要用于进程的首次调入,由程序员指出应调入哪些页
- 请求调页策略(运行期间的调入)
- 进程在运行需要访问的页面不在内存而提出请求,由系统将所需页面调入内存。
- 一定会被访问且容易实现
- 缺点是每次只调入一页,调入、调出页面数多时会花费过多的I/O开销
3.3.4.3从何处调入页面
请求分页系统中的外存分为两部分:用于存放文件的文件区和用于存放对换页面的对换区。
对换区通常采用连续分配方式,而文件区通常采用离散的分配方式,因此对换区的方式的磁盘I/O速度比文件区的I/O速度更快。【个人认为是连续分配方式可以只要起点和长度就可以一次读取。而离散要每次去找在外存的哪个位置,多了一定的访问消耗】
由此诞生了三种情况:
- 系统拥有足够的对换区空间
- 可以全部从对换区调入所需页面,以提高调页速度。因此进程运行前需将和该进程有关的文件从文件区复制到对换区。
- 系统缺少足够的对换区空间
- 凡是不会被修改的文件都直接从文件区调入;而当换出这些页面时,由于他们未被修改而不必再将他们换出。
- 但对于那些可能被修改的部分,在将它们换出时必须调换到对换区,以后需要时再从对换区调入。
- Unix方式
- 运行之前进程有关的数据全部放在文件区,故未使用过的页面,都可从文件区调入。
- 若被使用过的页面需要换出,则写回对换区,下次需要时从对换区调入。
3.3.5抖动
刚刚换出的页面马上又要换入内存,刚刚换入的页面马上又要换出外存,这种频繁的页面调度行为称为抖动(或颠簸)。
产生抖动的主要原因:进程频繁访问的页面数目高于可用的物理块数(分配给进程的物理块不够)
-
为进程分配的物理块太少,会使进程发生抖动现象。
-
为进程分配的物理块太多,又会降低系统整体的并发度,降低某些资源的利用率
-
抖动的预防方法
- 采用局部置换策略
- 把工作集算法融入到处理机调度中
- 利用”L=S“准则调节缺页率
- L是缺页之间的平均时间
- S是平均缺页服务时间。(置换一个页面所需的时间)、
- L比S大说明很少发生缺页,磁盘能力尚未得到充分的利用
- L比S小说明频繁发生缺页,缺页的速度已超过磁盘的处理能力。
- 只有当L和S相近的时候,磁盘和处理机都可达它们的最大利用率
- 选择暂停的进程
3.3.6工作集
工作集是指某段时间间隔内进程要访问的页面集合。
工作集反应了进程在接下来的一段时间内很有可能会频繁访问的页面集合。
因此如果分配给进程的驻留集小于工作集大小,则可能频繁缺页。所以一般来说驻留集大小要大于工作集大小。
当前时刻为滑动窗口右端点,工作集大小为滑动窗口大小
3.3.7请求分段式存储管理方式
段名 | 段长 | 段基址 | 存取方式 | 访问字段A | 修改位M | 存在位P | 增补位 | 外存始址 |
---|
3.3.8访问内存的有效时间(EAT)
λ:查找快表的时间
t:访问实际物理地址的时间
-
被访问页在内存中,且对应的页表项的在快表中
- EAT=λ+t
-
被访问页在内存中,对应的页表项的不在快表
- EAT=λ+t+t+λ(更新快表)
-
被访问页不在内存中
- 缺页中断处理时间 ϵ \epsilon ϵ
- EAT=λ+t+ ϵ \epsilon ϵ+t+λ
-
考虑快表的命中率、缺页率
- α-命中率 ,f-缺页率, ϵ \epsilon ϵ-缺页中断处理时间
- EAT= λ + α ∗ t + ( 1 − α ) [ t + f ( ϵ + t + λ ) + ( 1 − f ) ( t + λ ) ] \lambda+\alpha*t+(1-\alpha)[t+f(\epsilon+t+\lambda)+(1-f)(t+\lambda)] λ+α∗t+(1−α)[t+f(ϵ+t+λ)+(1−f)(t+λ)]
3.3.9补充
页故障:指的应该是缺页故障
基于局部性原理,在程序装入时将程序的一部分装入内存,而将其余部分留在外存,就可以启动程序。(应该是涉及预调页的策略)
虚拟存储器实际上并不存在,只是由于系统提供了部分装入、请求调入和置换功能后,给用户的感觉好像是存在一个比实际物理内存大得多的存储器。
4.文件管理
- 文件系统基础
- 文件的逻辑结构
- 顺序文件
- 索引文件
- 索引顺序文件
- 目录结构
- 文件控制块和索引结点
- 单级目录结构和两级目录结构
- 树形目录结构,图形结构目录
- 文件共享;文件保护;访问类型;访问控制
- 文件系统实现
- 文件系统层次结构;目录实现;文件实现
- 磁盘组织与管理
- 磁盘的结构;磁盘调度算法;磁盘的管理
考试对于磁盘考磁盘调度算法的大题,对于前面的部分考选填
5.输入/输出(I/O)设备管理
I/O控制方式
-
程序直接控制:由用户进程直接控制主存或CPU和外围设备之间的信息传送
-
中断驱动方式:外围设备仅当操作正常结束或异常结束时才向CPU发出中断请求
-
DMA方式:在 DMA 控制器的控制下,采用窃取或挪用总线控制权,在设备和主存之间开辟直接数据交换通道,成批地交换数据,而不必让CPU干预
-
通道方式:独立于 CPU 的专门负责输入输出控制的处理机,它控制设备与内存直接进行数据交换。有自己的通道指令,这些指令由CPU启动,并在操作结束时向CPU发出中断信号。
直接程序控制方式和中断程序控制方式适合于低速设备的数据传送,而 DMA 方式虽然适合于高速设备的数据传送,但一个 DMA 控制器只能控制少量的同类设备,这远远不能满足大型计算机系统的需要。通常,一个大型计算机需要连接大量的高速和低速设备,通道控制方式可以满足这个要求。(DMA和通道控制方式的主要区别——能否满足大型计算机系统的既能处理高速设备又能处理低速设备的需要)
缓冲区
SPOLLING技术对打印机的讲解:
在SPOOLING技术下,CPU要打印机打印的数据可以先输出到磁盘的输出井中(这个过程由输出进程控制),然后做其他的事情,若打印机此时被占用,则SPOOLING系统就会把这个打印请求挂到等待队列上,待打印机有空的时候再把数据打印出来
设备分配步骤:
①根据进程请求的物理设备名查找SDT(注:物理设备名是进程请求分配设备时提供的参数)
②根据SDT找到DCT,若设备忙碌则将进程PCB挂到设备等待队列中,不忙碌则将设备分配给进程。
③根据DCT找到COCT,若控制器忙碌则将进程PCB挂到控制器等待队列中,不忙碌则将控制器分配给进程。
④根据COCT找到CHCT,若通道忙碌则将进程PcB挂到通道等待队列中,不忙碌则将通道分配给进程