操作系统
- 概述
-
- 什么是操作系统
- 操作系统的功能
- 操作系统的特征
- 操作系统的运行机制
- 中断的分类
- 系统调用
- 进程管理
-
- 进程和线程
-
- 进程的特征
- 进程有哪几种状态?
- 线程有几种状态?
- 进程调度算法
- 线程同步
-
- 临界资源
- 同步和互斥的方式:
- 经典的线程同步和互斥的列子
- 进程间的通信的几种方式
- 死锁
-
- 什么是死锁?死锁产生的条件?
-
- 死锁的处理办法
- 鸵鸟策略
- 死锁预防
- 死锁避免的基本思想
-
- 安全状态
- 单个资源的银行家算法
- 多个资源的银行家算法
- 死锁解除
- 内存管理
-
- 程序的装入和链接
-
- 程序的装入
- 程序的链接
- 连续分配存储
- 非连续的内存分配
-
- 虚拟内存
-
- 颠簸
- 局部性原理
- 中断和轮询
- 一些算法总结
概述
什么是操作系统
- 是控制和管理整个计算机系统的硬件和硬件资源, 是计算机的基石
- 它也是一个运行在计算机的软件程序, 并且合理的组织调度计算机的工作和资源的分配
- 提供给用户和其他软件方便的接口和环境
- 操作系统存在屏蔽了硬件层的复杂性
- 操作系统的内核是操作系统的核心部分, 负责系统的内存管理、硬件设备的管理、文件系统的管理、应用城西的管理, 分为内核态和用户态, 内核态只提供给操作系统使用。
- 系统资源的管理者
操作系统的功能
1、进程管理。主要是对处理机进行管理。
2、存储管理。主要是对内存的分配、保护和扩充。
3、设备管理。对所有输人、输出设备的管理。
4、文件管理。主要涉及文件的逻辑组织和物理组织,目录的结构和管理。
5、作业管理。为用户提供一个友好的环境,方便用户组织自己的工作流程。
操作系统的特征
- 并发
- 并发在宏观上是同时发生的, 微观上看是交替进行的
- 而并行是同一时间一起发生
- 共享
- 资源共享, 指系统种的资源可供内存中多个并发执行的进程共同使用
- 两种资源共享方式
- 虚拟
- 异步
- 在多道程序环境下, 允许多个程序并发执行, 但由于资源有限, 进程的执行并不是一贯到底的, 而是走走停停, 以不可预知的速度向前推进。
- 并发以及共享是操作系统最基本的两大特征, 彼此互为存在条件
操作系统的运行机制
- 应用程序: 只能使用非特权指令
- 内核程序(操作系统内核): 可以使用特权指令, (通过状态字来判断现在处于, 内核态还是用户态)
- 中断时让操作系统内核夺回cpu使用权的唯一途径
中断的分类
- 内中断
- 外中断
- 中断的基本步骤:
- 外设请求中断 -> cpu在满足条件的情况下相应中断 -> 关中断 -> cpu保存cpu现场 -> 查找中断向量表 找到程序入口 -> 服务程序 -> 回复cpu现场 -> 开中断
- 对于内中断: cpu在执行指令的时候会检查是否有异常发生
- 对于外中断: 每个指令周期的末尾, cpu回检查是否有外中断信号需要处理。
系统调用
- 定义:是操作系统提供给应用程序使用的接口可以理解为一种可供应用程序调用的特殊函数, 应用程序可以通过系统调用来请求获得操作系统内核的服务。
- 也就是说在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。
- 这些系统调用按功能大致可分为如下几类:
- 设备管理。完成设备的请求或释放,以及设备启动等功能。
- 文件管理。完成文件的读、写、创建及删除等功能。
- 进程控制。完成进程的创建、撤销、阻塞及唤醒等功能。
- 进程通信。完成进程之间的消息传递或信号传递等功能。
- 内存管理。完成内存的分配、回收以及获取作业占用内存区大小及地址等功能。
- 操作系统会为统一的共享资源进行管理和分配,凡是与共享资源有关的操作, 就必须利用系统调用(陷入指令)提出服务请求。这样可以保证系统的稳定性和安全性
进程管理
进程和线程
程序:
- 是静态的, 就是个放在磁盘中的可执行文件】一系列的指令的集合。
进程
- 定义:
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动(程序的一次执行过程),进程是系统进行资源分配和调度的一个独立单位.
- 引入线程后, 进程只作为除cpu外的系统资源的分配单元。
- 同进程内的线程切换不需要切换进程的运行环境。
- 内核级线程切换是需要却换为内核态。
线程
- 线程一种轻量级线程, 是独立调度的基本单位
- 是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
(1)进程是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现操作系统的并发。
(2)线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发。
(3)一个程序至少有一个进程,一个进程至少有一个线程,线程依赖进程的存在。
(4)进程执行过程中拥有独立的内存单元,而多个线程共享进程的内存。
区别
Ⅰ 拥有资源
进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。
Ⅱ 调度
线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
Ⅲ 系统开销
由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。
Ⅳ 通信方面
线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。
进程的特征
进程有哪几种状态?
-
创建状态
-
就绪状态:进程已获得除处理机以外的所需资源,等待分配处理机资源;
-
运行状态:占用处理机资源运行,处于此状态的进程数小于等于CPU数;
-
阻塞状态: 进程等待某种条件,在条件满足之前无法执行;
-
终止状态
-
状态切换
-
七状态模型
线程有几种状态?
- 新建(NEW):新创建了一个线程对象。
- 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
- 运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
- 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
- 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
在给定的时间点上,一个线程只能处于一种状态。
进程调度算法
-
先来先服务(FCFS)
非抢占式的调度算法,按照请求的顺序进行调度。
有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。
-
短作业优先(SjF)
非抢占式的调度算法,按估计运行时间最短的顺序进行调度。
长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
-
抢占式的短作业优先(SPF)
有作业来的时候都要看一下作业的剩下运行时间
-
高响应比算法(HRRN 非抢占式):
- 相应比 = (等待时间 + 要求服务的) / (要求服务的时间)
-
时间片轮换算法(RR)划分服务时间片适合分时操作系统 抢占式算法 响应时间短
- 将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。
- 时间片轮转算法的效率和时间片的大小有很大关系:
因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。而如果时间片过长,那么实时性就不能得到保证。
-
优先级调度算法
- 非抢占
- 抢占
- 静态优先级 动态优先级 (I/0设备优先级高)
-
多级反馈队列调度算法
- 来一个进程先放到第一级队列
-
线程同步
- 线程同步是两个或多个共享关键资源的线程的并发执行。应该同步线程以避免关键的资源使用冲突。
- 满足的条件
临界资源
对临界资源进行访问的那段代码称为临界区。
为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
同步和互斥的方式:
- 互斥量(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如 Java 中的 synchronized 关键词和各种 Lock 都是这种机制。wait(P操作) signal(V操作)
- 信号量(Semphares) :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量 wait(P操作) signal(V操作)
- 事件(Event) :Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操
- 对于互斥也是利用信号量中的记录信号量
- 管程
-
使用信号量机制实现的生产者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。类似于java的sychronized以及lock
-
管程有一个重要特性:在一个时刻只能有一个进程使用管程。进程在无法继续执行的时候不能一直占用管程,否则其它进程永远不能使用管程。
-
管程引入了 条件变量 以及相关的操作:wait() 和 signal() 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal() 操作用于唤醒被阻塞的进程
经典的线程同步和互斥的列子
- 生产者与消费者问题
- 哲学家进餐问题
- 读者写者问题
- 解答:例子
进程间的通信的几种方式
- 各进程的内存地址空间相互独立。一个进程不能直接访问另一个进程的地址空间。
- 管道(pipe)及匿名管道(named pipe):半双工通信。 管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
- 有名管道: 支持无亲缘关系的进程间的通信, 有名管道严格遵循先进先出。名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
- 信号(signal): 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生;
- 消息队列: 消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识。管道和消息队列的通信数据都是先进先出的原则。与管道(无名管道:只存在于内存中的文件;命名管道:存在于实际的磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即,操作系统重启)或者显示地删除一个消息队列时,该消息队列才会被真正的删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比 FIFO 更有优势。消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺点。
- 信号量: 主要作为进程之间及同一种进程的不同线程之间得同步和互斥手段;信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。这种通信方式主要用于解决与同步相关的问题并避免竞争条件。
- 共享内存: 可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等;进程之间的访问是互斥的。
- 套接字: 这是一种更为一般得进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。
- 基于文件的:进程通信在同一台机器的环境中, 套接字是基于本地文件实现的, 一个套接字关联到一个特殊的文件, 通信双方通过堆这个特殊文件的读写实现通信, 原理类似管道。
- 基于网络的
- 几种方式的比较:
- 管道:速度慢、容量有限
- 消息队列:容量收到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题。
- 信号量:不能传递复杂信息,只能用来同步。
- 共享内存:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全。
死锁
什么是死锁?死锁产生的条件?
-
死锁的概念
在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗的讲,就是两个或多个进程无限期的阻塞、相互等待的一种状态。
-
死锁产生的四个必要条件
-
互斥:至少有一个资源必须属于非共享模式,即一次只能被一个进程使用;若其他申请使用该资源,那么申请进程必须等到该资源被释放为止;
-
占有并等待:一个进程必须占有至少一个资源,并等待另一个资源,而该资源为其他进程所占有;
-
非抢占:进程不能被抢占,即资源只能被进程在完成任务后自愿释放
-
循环等待:若干进程之间形成一种头尾相接的环形等待资源关系
-
死锁的处理基本策略和常用方法
解决死锁的基本方法主要有 预防死锁、避免死锁、检测死锁、解除死锁 、鸵鸟策略 等。
死锁的处理办法
主要有四种处理办法
鸵鸟策略
把头埋在沙子里,假装根本没发生问题。
因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。
当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。
大多数操作系统,包括 Unix,Linux 和 Windows,处理死锁问题的办法仅仅是忽略它。
死锁预防
-
死锁预防的基本思想是 只要确保死锁发生的四个必要条件中至少有一个不成立,就能预防死锁的发生,具体方法包括:
打破互斥条件:允许进程同时访问某些资源。但是,有些资源是不能被多个进程所共享的,这是由资源本身属性所决定的,因此,这种办法通常并无实用价值。
-
打破占有并等待条件:可以实行资源预先分配策略(进程在运行前一次性向系统申请它所需要的全部资源,若所需全部资源得不到满足,则不分配任何资源,此进程暂不运行;只有当系统能满足当前进程所需的全部资源时,才一次性将所申请资源全部分配给该线程)或者只允许进程在没有占用资源时才可以申请资源(一个进程可申请一些资源并使用它们,但是在当前进程申请更多资源之前,它必须全部释放当前所占有的资源)。但是这种策略也存在一些缺点:在很多情况下,无法预知一个进程执行前所需的全部资源,因为进程是动态执行的,不可预知的;同时,会降低资源利用率,导致降低了进程的并发性。
-
打破非抢占条件:允许进程强行从占有者哪里夺取某些资源。也就是说,但一个进程占有了一部分资源,在其申请新的资源且得不到满足时,它必须释放所有占有的资源以便让其它线程使用。这种预防死锁的方式实现起来困难,会降低系统性能。
-
打破循环等待条件:实行资源有序分配策略。对所有资源排序编号,所有进程对资源的请求必须严格按资源序号递增的顺序提出,即只有占用了小号资源才能申请大号资源,这样就不回产生环路,预防死锁的发生。
死锁避免的基本思想
死锁避免的基本思想是动态地检测资源分配状态,以确保循环等待条件不成立,从而确保系统处于安全状态。资源分配图算法和银行家算法是两种经典的死锁避免的算法,其可以确保系统始终处于安全状态。其中,资源分配图算法应用场景为每种资源类型只有一个实例(申请边,分配边,需求边,不形成环才允许分配),而银行家算法应用于每种资源类型可以有多个实例的场景。
安全状态
图 a 的第二列 Has 表示已拥有的资源数,第三列 Max 表示总共需要的资源数,Free 表示还有可以使用的资源数。从图 a 开始出发,先让 B 拥有所需的所有资源(图 b),运行结束后释放 B,此时 Free 变为 5(图 c);接着以同样的方式运行 C 和 A,使得所有进程都能成功运行,因此可以称图 a 所示的状态时安全的。
所谓安全状态是指:如果系统能按某个顺序为每个进程分配资源(不超过其最大值),那么系统状态是安全的,换句话说就是,如果存在一个安全序列,那么系统处于安全状态。
单个资源的银行家算法
一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是,就拒绝请求;否则予以分配。
多个资源的银行家算法
对于用户的需求如果满足每个资源的请求都不会进入不安全序列就分配,否则就拒绝。
死锁解除
死锁解除的常用两种方法为进程终止和资源抢占。所谓进程终止是指简单地终止一个或多个进程以打破循环等待,包括两种方式:终止所有死锁进程和一次只终止一个进程直到取消死锁循环为止;所谓资源抢占是指从一个或多个死锁进程那里抢占一个或多个资源,此时必须考虑三个问题:
(I). 选择一个牺牲品
(II). 回滚:回滚到安全状态
(III). 饥饿(在代价因素中加上回滚次数,回滚的越多则越不可能继续被作为牺牲品,避免一个进程总是被回滚)
内存管理
程序的装入和链接
程序的装入
这个解决的是程序如何装入内存中。
- 有三种方式
- 绝对装入
只能运行单道程序。
- 可重定位装入(静态装入)
在要装入的时候将逻辑地址转化为物理地址, 这是内存中存的还是绝对地址(在装入之后是不会改变的)。
- 动态运行时装入
他可以装入内存的任何位置, 内存中存的是逻辑地址, 到真正运行的时候才进行转换。 利用重定位寄存器实现。
程序的链接
这个解决的问题是如何让程序进行编译后形成的一组目标模块, 以及将所需的库函数链接在一起,如何 可以进行调用。
- 三种链接方式
- 静态链接方式
在程序运行的时候就把各目标所需的库函数链接成一个完整的整体, 形成一个可执行的文件之后不再拆开
- 装入时动态链接
在装入内存的时候才会链接起来, 将调用的地址改为绝对地址
- 运行时动态链接
在程序执行时需要目标模块时才会对他进行链接。便于修改和更新, 便于实现目标模块的共享。
连续分配存储
- 单一连续分配
- 只把内存分为系统区和用户区, 用于单用户单任务操作系统
- 固定分区分配
- 将内存分为大小相等的分区 其缺点时缺乏灵活性吗当程序太小时会出现内部碎片, 当程序太大的时候又无法运行
- 分区大小不等, 建立分区表
- 优点: 利于多个相同对象的控制系统中, 缺点造成浪费空间
- 动态分区分配(有外部碎片不会有内部碎片)
- 利用空闲分区表或者空闲分区链来记录空闲的分区, 利用四种分区分配算法进行内存分配和回收
- 动态分区算法
- 首次适应算法(FF):从链首找到第一个满足需求的给予分配, 没有找到拒绝。
- 有点优先使用内存低地址的地方, 保留高地址的大内存, 利于大作业的分配
- 缺点, 会出现很多无法利用的非常小的外部碎片
- 循环首次适应算法(NF):与首次适应算法一致, 只不过查找是本次从上一次查找到的分区进行查找。
- 最佳适应算法(BF)
- 对空闲分区从小到大进行排序, 找到第一个满足要求的分区进行分配
- 优点: 有大的空闲分区
- 缺点: 会出现有很多无法利用的外部碎片,维护需要额外的空间
- 最坏适应算法(WF): 从大到小排序 每次找最大的
- 优点:克服了最佳适应算法有很多无法利用的外部碎片的缺点
- 缺点: 缺乏大的空闲分区, 维护麻烦
非连续的内存分配
分页存储管理方式
- 页或者页面: 将程序分为若干个固定大小的区域
- 页框: 将内存区域分为固定大小的区域
- 一般都把内存分为2的整数倍, 这样利于地址的转换
- 页表:将程序的逻辑地址对应到内存的物理地址
- 内存地址结构:分为页号和页内地址
- 转换流程
分段存储管理方式
- 引入分段存储管理方式的意义: 满足用户在编程和使用上多方面的要求,
- 分段的内存结构 : 段号 + 段内地址
- 段表组成: 段号 + 段大小 + 内存始值
- 转换过程
区别
-
对程序员的透明性:分页透明,但是分段需要程序员显式划分每个段。
-
地址空间的维度:分页是一维地址空间,分段是二维的。
-
大小是否可以改变:页的大小不可变,段的大小可以动态改变。
-
出现的原因:分页主要用于实现虚拟内存,从而获得更大的地址空间;分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护。
-
目的不同:分页是由于系统管理的需要而不是用户的需要,它是信息的物理单位;分段的目的是为了能更好地满足用户的需要,它是信息的逻辑单位,它含有一组其意义相对完整的信息;
-
大小不同:页的大小固定且由系统决定,而段的长度却不固定,由其所完成的功能决定;
-
地址空间不同: 段向用户提供二维地址空间;页向用户提供的是一维地址空间;
-
信息共享:段是信息的逻辑单位,便于存储保护和信息的共享,页的保护和共享受到限制;
-
内存碎片:页式存储管理的优点是没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满);而段式管理的优点是没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)。
虚拟内存
虚拟内存的目的是为了让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。
每次只装入当前要执行的部分程序, 如果当前功能要用到另一部分程序在进行调入。故此可以扩大内存。 也就是为什么我们内存只有16GB却能运行60GB的游戏。
- 特征
- 多次性: 无需载作业运行的时候把程序全部调入内存
- 对换性: 在作业运行的时候无需长时间驻留在内存中, 需要对作业进行换入换出。
- 虚拟性: 从逻辑上扩充了内存, 使用户看到的内存大于实际内存。
虚拟内存技术的实现
- 请求分页
- 请求分段
- 请求段页
- 他们与之前的哪三种的存储管理多了两个步骤: 当访问的信息不在内存时, 由操作系统负责将所需信息从外存调入内存(调页和调段), 然后继续执行程序,若内存空间不够的时候, 由操作系统负责将内存中暂时用不到的信息换出到外存(页面置换)。
请求分页存储管理
- 页表改为这样
- 多了一个缺页中断机构, 当访问的页面不存在的时候就产生了缺页中断, 然后又操作系统的缺页中断处理程序处理中断此时缺页的进程阻塞, 放入阻塞队列, 调页完成后再进行唤醒, 放回就绪队列。
页面置换算法
-
OPT(Optimal replacement)最优置换算法:理论的最优,理论;就是要保证置换出去的是不再被使用的页,或者是在实际内存中最晚使用的算法, 无法实现。
FIFO先进先出算法:在操作系统中经常被用到,比如作业调度(主要实现简单,很容易想到);
-
LRU(Least recently use)最近最少使用算法:根据使用时间到现在的长短来判断;
虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近最久未使用的页面换出。
为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。
因为每次访问都需要更新链表,因此这种方式实现的 LRU 代价很高。
虚拟内存的应用与优点
虚拟内存很适合在多道程序设计系统中使用,许多程序的片段同时保存在内存中。当一个程序等待它的一部分读入内存时,可以把CPU交给另一个进程使用。虚拟内存的使用可以带来以下好处:
- 在内存中可以保留多个进程,系统并发度提高
- 解除了用户与内存之间的紧密约束,进程可以比内存的全部空间还大
颠簸
- 颠簸本质上是指频繁的页调度行为,具体来讲,进程发生缺页中断,这时,必须置换某一页。然而,其他所有的页都在使用,它置换一个页,但又立刻再次需要这个页。因此,会不断产生缺页中断,导致整个系统的效率急剧下降,这种现象称为颠簸(抖动)。
- 内存颠簸的解决策略包括:
- 如果是因为页面替换策略失误,可以修改替换算法来解决这个问题;
- 如果是因为运行的程序太多,造成程序无法同时将所有频繁访问的页面调入内存,则要降低多道程序的数量;
- 否则,还剩下两个办法:终止该进程或增加物理内存容量。
局部性原理
(1) 时间上的局部性:最近被访问的页在不久的将来还会被访问;
(2) 空间上的局部性:内存中被访问的页周围的页也很可能被访问。
中断和轮询
-
中断的定义
指在计算机执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程
-
轮询的定义
定时对各种设备轮流询问一遍有无处理要求
-
临界区和冲突解决
-
缓冲区溢出
- 缓冲区溢出的定义:
指当计算机向缓冲区内填充数据时超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上
-
缓冲区溢出的危害:
程序崩溃导致拒绝服务、跳转并且执行一段恶意代码
-
缓冲区溢出的原因:
程序中没有仔细检查用户输入的参数
一些算法总结
- 进程调度算法
- .先来先服务调度算法(FCFS)
- 短作业优先 (SJF, 抢占式的是SPF)
- 优先级调度算法
- 高响应比优先算法
- 时间片轮转算法 (多用于分时操作系统)
- 多级反馈队列算法
- 动态分区分配算法
- 首次适应算法(FF)
- 循环(邻近)适应算法 (NF)
- 最佳适应算法 (BF)
- 最坏适应算法 (WF)
- 页面置换算法
- 先进先出算法 (FIFO)
- 最佳置换算法 (OPT) : 理想的、
- 最近最久未使用置换算法LRU
- 最少使用LFU
- 简单时钟置换算法(CLOCK/NRU)
- 优化时钟算法