操作系统总结
1. 计算机硬件
现代计算机由运算器、存储器、控制器、I/O设备组成。
- 运算器用来完成算术运算和逻辑运算,并将运算中间结果,暂存在运算器内;
- 存储器用来存放数据和程序;
- 控制器用来控制、指挥程序和数据的输入、运行以及处理运算结果;
- I/O设备分别用来实现程序数据的输入和计算结果的输出。
五大部件实际上是在控制器的控制下协调统一地工作。
- 把表示计算步骤的程序和计算中需要的原始数据,在控制器输入命令的控制下,通过输入设备送入计算机的存储器存储。
- 当计算开始时,在取指令作用下把程序指令逐条送入控制器。控制器对指令进行译码,并根据指令的操作要求向存储器和运算器发出存储、取数命令和运算命令,经过运算器计算并把结果存放在存储器内。
- 在控制器的取数和输出命令作用下,通过输出设备输出计算结果。
运算器和控制器在逻辑关系和电路结构上联系十分紧密,这两个部件往往集成在同一芯片上,通常将它们合起来统称为中央处理器,即CPU。所以现代计算机通常有三部分构成:CPU、存储器、I/O设备。
1.1 CPU(控制器+运算器)
CPU的工作核心是从程序或应用程序中获取指令并且执行计算,由控制器和运算器构成。这个过程一共有三个关键阶段:提取,解码和执行。
控制器:CU(Controller Unit)控制器作为计算机系统的指挥中心,其主要功能有:
- 从主存中取出指令,指出下一条指令的地址。
- 进行指令译码、测试,产生对应的控制信号。
- 指挥并控制CPU、主存、输入和输出设备之间的数据流动方向。
指令是指示计算机如何工作的一步操作。上述工作周而复始,保证了计算机能自动连续地工作。
控制器的基本组成
- 程序计数器(Program Counter,PC):也叫指针寄存器,用于指出下一条指令在主存中的存放地址。CPU根据PC的内容去主存中寻找指令。因为程序中的指令通常是顺序执行的,所以PC有自增功能。
- 指令寄存器(Instuction Register,IR):用于保存当前正在执行的指令。
- 存储器地址寄存器:用于存放即将访问的主存单元的地址。
- 存储器数据存储器:用于存放向主存中写入的内容或者从主存中读出的内容。
- 指令译码器(Instruction Decoder,ID):用来对指令寄存器中的指令进行译码分析,指出指令的操作种类和寻址方式,指令译码器的输出作为微操作命令发生器的输入,是产生控制信号的主要依据。
- 时序电路:用于控制操作时间的信号称为时序控制信号。时序电路产生并发出计算机所需的各种时序控制信号,对各种操作进行时间上的控制。时序控制信号有机器周期信号、节拍信号、工作脉冲信号,它们决定每个微操作的开始时刻和操作的持续时间
- 微操作命令发生器:微操作就是不能再分解的操作,执行微操作总是需要相应的控制信号(也称为微操作控制命令)。微操作命令发生器根据指令操作码、时序信号、状态寄存器内容和其他一些信息,产生计算机工作需要的各种控制信号,以便建立正确的数据通路,完成对取指令、分析指令和执行指令的控制。
运算器也称为算术逻辑单元ALU(Arithmetic Logic Unit)。它的功能是完成算术运算和逻辑运算。算术运算是指加、减、乘、除及它们的复合运算。而逻辑运算是指“与”、“或”、“非”等逻辑比较和逻辑判断等操作。在计算机中,任何复杂运算都转化为基本的算术与逻辑运算,然后在运算器中完成。
-
算术逻辑单元:主要功能是进行算术/逻辑运算
-
暂存寄存器:用于暂存从主存读来的数据,该数据不能存放在通用寄存器中,否则会破坏原有内容。对于应用程序而言,暂存寄存器是透明的。
-
累加寄存器:是一个通用寄存器,用于暂时存放ALU运算的结果信息,可以作为加法运算的一个输入端。
-
通用寄存器组:如AX、BX、CX、DX、SP等,用于存放操作数(包括源操作数、目的操作数及中间结果)和各种地址信息。SP是堆栈指针,用于表示栈顶的地址。
-
程序状态字寄存器:保留由算术逻辑运算指令或测试指令的结果而建立的各种状态细信息,如溢出标志(OF)、符号标志(SF)、零标志(ZF)、进位标志(CF)等。PSW中的位参与并决定微操作的形成。
-
移位器:对操作数或者运算结果进行移位操作。
-
计数器:控制乘除运算的操作步数。
1.2 存储器
一个计算机系统中可能存在各种各样的存储器,有CPU内部的寄存器、CPU内的Cache,CPU外的Cache,主板上的主存(内存),主板外的磁盘存储器等等。
主存-辅存层次:为了解决容量问题
缓存-主存层次:为了解决速度问题
存储设备:
- 主存
- 1.随机存储器(Random Access Memory,RAM)是构成内存的主要部分,其内容可以根据需要随时按地址读出或写入,以某种电触发器的状态存储,断电后信息无法保存,用于暂存数据,又可分为DRAM(信息会随时间逐渐消失)和SRAM(在不断电的情况下,信息一直保存)两种
- 2.只读内存(Read-Only Memory,ROM)出厂时其内容由厂家写好,信息已固化在存储器中,只可读出,无法改写
- 辅存
- 1.硬盘:有固态硬盘(SSD 盘,新式硬盘)、机械硬盘(HDD 传统硬盘)、混合硬盘(HHD 一块基于传统机械硬盘诞生出来的新硬盘)。存储资料和软件等数据等,有容量大,断电数据不丢失的特点。
- 2.软盘:软盘存取速度慢,容量也小,但可装可卸、携带方便。
- 3.。。。。
- 缓存:缓存就是数据交换的缓冲区(称作Cache),是介于cpu和主存之间的小容量存储器,存取速度比主存快。能高速的向cpu提供指令和数据,加快程序的执行速度,它的内容为主存一部分内容的副本。当存储器接到有关读取指令时,现在cache中查找此信息是否存在,若有则不经主存直接从cache中取出,否则直接从主存取出,同时写入cache,以备再次使用。cache目的是为了解决cpu和主存速度不匹配的技术。cache用来存放程序中当前最活跃的程序和数据。
1.3 I/O设备
计算机的输入输出设备
a) 按使用特性分类,可以划分为:
- 存储设备,如磁盘、磁带、光盘等。
- 输入/输出设备,如打印机、键盘、显示器、音声输入/输出设备等等。
- 终端设备,包括通用终端、专用终端和虚终端。
- 脱机设备。
b) 按所属关系分类,可划分为:
- 系统设备,指在操作系统生成时已经等机载系统中的标准设备,如打印机、 磁盘等,时钟也是一系统设备。
- 用户设备,指在系统生成时未登记在系统中的非标准设备
c) 按资源分配分类,可划分为:
- 独占设备,通常分配给某个进程,在该进程释放之前,其他进程不能使用。 如打印机和纸带读入机。
- 共享设备,允许若干个进程同时使用。如磁盘机
- 虚拟设备,通过假脱机技术把原来的独占设备改造成若干进程所共享的设 备,以提高设备的利用率。
d) 按传输数据数量分类,可划分为:
- 字符设备,如打印机、终端、键盘等低速设备
- 块设备,如磁盘、磁带等高速外存储器
2. 操作系统概述
操作系统(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是用户和计算机的接口,同时也是计算机硬件和其他软件的接口。
操作系统的功能包括管理计算机系统的硬件、软件及数据资源,控制程序运行,改善人机界面,为其它应用软件提供支持等,位于应用软件和计算机硬件之间。
2.1 单核CPU,多核CPU,多CPU
1.CPU个数即CPU芯片个数。
2.CPU的核心数是指物理上,也就是硬件上存在着几个核心。比如,双核就是包括2个相对独立的CPU核心单元组,四核就包含4个相对独立的CPU核心单元组。
多核CPU即多个CPU组成,这些CPU集成在一个芯片里。这些CPU中分配出一个独立的核执行操作系统,这些核通过CPU内部总线来交互数据,共享数据,缓存,并且工作是并行的,资源分配是由操作系统来完成的,操作系统来决定程序cpu的控制权分配。
多CPU即拥有多个CPU的主机,每个CPU只能用来独立执行不同的程序,这些CPU都是单核的,每个CPU有自己的总线,一级二级缓存;多个CPU之间的通讯是通过主板上的总线进行的。
2.2 用户态和内核态
内核态与用户态是操作系统的两种运行级别
- 内核态(Kernel Mode):运行操作系统程序,操作硬件
- 用户态(User Mode):运行用户程序
指令划分
- 特权指令:只能由操作系统使用、用户程序不能使用的指令。
- 启动- I/O
- 内存清零
- 修改程序状态字
- 设置时钟
- 允许/禁止终端
- 停机
- 非特权指令:用户程序可以使用的指令。
- 控制转移
- 算数运算
- 取数指令
- 访管指令(使用户程序从用户态陷入内核态)
特权级别
- R0、R1、R2和R3(0最高,3最低);
- R0相当于内核态,R3相当于用户态;
- 不同级别能够运行不同的指令集合;
CPU状态之间的转换
- 用户态—>内核态:唯一途径是通过中断、异常、陷入机制(访管指令)
- 内核态—>用户态:设置程序状态字PSW
内核态与用户态的区别
- 处于用户态执行时,进程所能访问的内存空间和对象受到限制,其所处于占有的处理器是可被抢占的
- 处于内核态执行时,则能访问所有的内存空间和对象,且所占有的处理器是不允许被抢占的。
用户态和内核态的切换
- 系统调用: 用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。
- 异常: 在程序运行时产生异常事件(如在目态下执行特权指令),运行程序被打断,转向异常处理程序工作,如缺页异常。
- 外围设备中断: 在程序运行时产生中断事件(如I/O操作完成),运行程序被中断,转向中断处理程序处理。
这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以是用户进程主动发起的,异常和外围设备中断则是被动的。
2.3 单道批处理 VS 多道批处理
单道批处理:为了实现对作业的连续处理,需要先把一批作业以脱机方式输入到磁盘上,并在系统中配上监督程序(Monitor),在它的控制下,使得这批作业能一个接着一个的连续工作。
多道批处理:内存中存放多道程序,当某道程序因某种原因如执行I/O操作时而不能继续运行放弃CPU时,操作系统便调度另一程序运行,即:内存中多道程序轮流占有CPU,交替执行,这样CPU就尽量忙碌,达到提高系统效率的目的。
2.4 中断和异常机制
中断: 程序执行过程中遇到急需处理的事件时,暂时终止现行程序在CPU上的运行,转而执行相应的事件处理程序,待处理完成后再返回断点或调度其他程序的执行过程。
中断机制是为了弥补CPU速度和外设速度数量级差异的机制
- 外中断,又称中断(interrupt)或异步中断,来自处理器之外的中断信号。与同步中断相反,异步中断可在任何时间产生,包括指令执行期间。
- 内中断,又称异常或同步中断,来自处理器内部的中断信号。这里同步是指中断请求信号与代码指令之间的同步执行,在一条指令执行完毕后,CPU才能进行中断,不能在执行期。
从广义上讲,中断又可分为四类:外中断(中断)、内中断(故障、陷阱、终止)。
中断类别及其行为
中断和异常的响应: 发现中断源 → 保护现场 → 转向中断/异常事件处理程序执行 → 恢复现场
2.5 并发与并行
- 并发( Concurrency ):指两个或多个事件在同一个时间段内发生(各个事件交替发生)。同一时刻,只有个事物处于活动状态。
- 并行( ParallelParallel ):指两个或多个事件在同一时刻发生(同时发生)。同一时刻,两个事物均处于活动状态
2.6 同步与异步
- 同步(Sync):发出一个功能调用时,在没有得到结果之前,该调用就不返回或继续执行后续操作。
简单的来说,同步就是必须一件一件事情做,等前一件做完才可以做下一件。 - 异步(Async):当一个异步被调用触发的时候,调用者在没有得到结果之前就可以做操作,当调用完成后一般通过回调,通知,状态来通知调用者,异步调用调用的返回不受到调用者的控制。
3. 进程管理
3.1 进程概念
进程是指计算机中已运行的程序,每个进程都有一个独立的内存空间;是系统进行资源分配和调度的基本单位。
进程实体:程序被载入到内存之后,会被划分为程序段和数据段,操作系统会为该进程构建一个叫进程控制块(PCB)的数据结构,用以记录该进程的各种信息(包括程序段和数据段的位置);而进程实体=PCB+程序段+数据段。
进程控制块(Process Control Block, PCB)——进程存在的唯一标识,来描述进程的基本情况和运行态。包括标识信息、现场信息和控制信息等信息。
用户栈和核心栈
- 用户栈是用户进程空间中的一块区域。用于保存应用程序的子程序(函数)间相互调用的参数,返回值,返回点和子程序的局部变量。
- 核心栈是内存中操作系统空间的一块区域。用于保存中断现场和保存操作系统程序(函数)间相互调用的参数,返回值,返回点和程序的局部变量。
3.2 进程状态及状态转换
- 创建态(1、申请一个空白的PCB;2、系统分配运行所需资源;3、初始化PCB;4、转为就绪态 )
- 就绪态(获得了除处理机外的所有资源)
- 运行态(一个处理机同时只有一个进程处于运行态)
- 阻塞态(等待态,等待获取除处理机外的其他资源。如I/O资源)
- 结束态(先置为结束态,再处理和回收资源)
五状态转换图
七状态转换图
- 阻塞–>阻塞挂起:没有进程处于就绪状态或就绪进程要求更多内存资源时,以提交新进程或运行就绪进程;
- 就绪–>就绪挂起:当有高优先级就绪进程和低优先级就绪进程,系统挂起低优先级进程
- 运行–>就绪挂起:对抢先氏分时系统当有高优先级阻塞挂起进程因事件出现进入挂起就绪时,系统可能会把运行进程转到就绪状态
挂起和阻塞最大的区别我想是数据所在的位置。当内存空间比较紧缺的时候,如果有存在在内存中的,而且是处于阻塞状态的进程,那么就让他更需要内存的程序占用内存,自己进入阻塞挂起状态,PCB等数据存入外存,而阻塞后,数据仍留在主存中,只有阻塞挂起状态下数据才被调到外存上,PCB常驻内存。
3.3 进程的组织
进程的组成讨论的是一个进程内部由哪些部分组成的问题,而进程的组织讨论的是多个进程之间的组织方式问题,即对进程进行有效管理的问题。进程的组织方式有两种,链接方式和索引方式
- 锁链方式:
- 索引方式:
3.4 进程通信
指进程之间的信息交换
- 共享存储:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问,对这段内存的访问是互斥的。
- 管道通信:
- “管道”是指用于连接一个写进程和一个读进程以实现它们之间的通信的共享文件,即pipe文件,
- 管道是一个缓冲区,写满才可以读,读空才可以写的,管道的使用对于各个进程是互斥的。
- 管道是半双工的,只能单向通信,要实现双向需定义两个管道。
- 消息传递:消息传递系统中,进程间的数据交换是以格式化的消息为单位的。操作系统有发送消息和接收消息两种原语可供调用。
- 直接通信(直接发送到对方的信息队列里)
- 间接通信(先发送到中间体“信箱”里,进程使用接收原语取走信箱里自己的消息)
3.5 进程具有的属性
- 进程是一个可拥有资源的基本单位
- 进程是可独立调度和分派的基本单位
- 进程作为一个资源拥有者,在创建、撤销、切换中,系统必须为之付出较大的时空开销
所以这也就导致了进程自身的一些局限性:
系统中进程的数量不宜过多,系统切换进程的频率不宜过高。
这就限制了并发度的进一步提高。
于是为解决此问题,人们想到将进程的上述两个属性分开:
对作为操作系统调度和分派的基本单位,不同时作为独立分配资源的基本单位,线程由此产生。
3.6 线程
线程是进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。
一个线程包含以下内容。
- 一个指向当前被执行指令的指令指针;
- 一个栈;
- 一个寄存器值的集合,定义了一部分描述正在执行线程的处理器状态的值;
- 一个私有的数据区。
3.7 线程与进程比较
-
根本区别:进程是资源分配和调度的基本单位,而线程是处理器任务调度和执行的基本单位
-
资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
-
包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
-
内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的
-
影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
-
执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行
3.8 处理器调度
进程调度:当多个进程同时进入就绪状态时,因为CPU只有一个,那么这时候就需要做一个选择:到底接下来该选择哪个进程运行。操作系统做这个选择的部分就叫做调度器(scheduler),而使用到的算法叫做调度算法(scheduling algorithm)。
3.8.1 调度的层次
- 作业调度(高级调度)
从外存选择一个进程分配除cpu外的资源,每个作业只调入调出一次。 - 内存调度(中级调度)
不处于运行态的进程挂到外存,处于挂起态,当具备运行条件且内存空闲,调入内存,挂在就绪队列等待。 - 进程调度(低级调度)
以某种策略从就绪队列选取一个进程分配CPU资源。
3.8.2 进程调度方式
- 非剥夺调度方式(非抢占方式)
当有更加紧急的进程进入就绪队列时当前进程不会立即终止直到进程终止或进入阻塞态。实现简单开销小。 - 剥夺调度方式(抢占方式)
如果有进程正在运行,当一个更重要或者更紧急的进程需要运行时,立即停止正在运行的进程,运行该进程。
3.8.3 典型调度算法
- 先来先服务(First Come First Server, FCFS)算法。
- 短作业优先(Shortest Job First, SJF)算法。
- 最短剩余时间优先(Shortest Remaining Time First, SRTF)算法: 假设当前某进程/线程正在运行,如果有新进程/线程移入就绪队列,若它所需的CPU运行时间比当前运行的进程/线程所需的剩余CPU时间还短,抢占式最短作业优先算法强行剥夺当前执行者的控制权,调度新进程/线程执行。
- 最高响应比优先(Highest Response Ratio First, HRRF)算法:非剥夺式算法。其中,响应比 = (作业已等待时间 + 作业处理时间) / 作业处理时间。
- 优先级调度算法:优先级高的选择进程/线程优先选择。
优先级:
- 系统进程>用户进程
- 交互型进程>非交互型进程
- IO型进程>计算型进程
- 轮转调度(Round-Robin, RR)算法: 也称时间片调度。就绪队列的进程轮流运行一个时间片,主要用于分时系统中的进程调度。。
- 多级反馈队列(Multi-Level Feedback Queue, MLFQ)算法。
3.9 进程交互
3.9.1 相关概念
-
进程互斥(Mutual Exclusion,间接制约关系): 若干进程因相互抢夺独占型资源而产生的竞争制约关系。
-
进程同步(Synchronization,直接制约关系)进程间为了完成某个任务需要按特定次序等待、传递信息的相互协作的过程。
-
临界资源:各进程采取互斥的方式,实现共享的资源称作临界资源(打印机,某些数据等等)
-
临界区(criticalsection):每个进程中访问临界资源的那段代码
对临界资源的访问,逻辑上可分为以下四部分:
为禁止两进程同时进入临界区,同步机制应遵循以下准则:
3.9.2 临界资源互斥算法
-临界资源互斥的软件实现方法
-
单标志法(违背空闲让进,当前一直循环,只有时间片结束其他进程才可以用)
-
双标志先检查法(违背忙则等待)
检查和上锁不是一气呵成的,①②之间发生切换,导致两个检查进程都进入临界区 -
双标志后检查法(违背空闲让进、有限等待)
-
。Alogorithm(皮特森算法,不满足让权等待)
争取-------谦让-------检查
- 临界资源互斥的硬件实现方法
- 中断屏蔽方法:利用开/关中断指令实现,限制了处理机交替执行的能力,效率低,关中断的权利交给用户不安全。
- TestAndSet指令,该指令执行时不允许被中断,该指令保证了检查和上锁一气呵成
3.9.3 信号量机制(解决同步和互斥问题)
用信号量(S)表示某种资源的数量,只能被wait(S)和signal(S)两个原语访问,它们在执行时是不可中断的,解决同步和互斥问题。记为P操作和V操作。
-
整型信号量
在整型信号量机制中的wait操作中,只要是信号量S<=0,就会不断地测试(一直while直到时间片用完才切换进程)。因此该机制没有遵循“让权等待”准则,而是使进程处于“忙等”的状态。 -
记录型信号量(比较完美的一个实现方式,去掉了while循环,添加了阻塞和唤醒,解决了忙等),
3.9.4 经典进程同步问题
- 生产者和消费者问题
- 在缓冲区为空时,消费者不能再进行消费(同步)
- 在缓冲区为满时,生产者不能再进行生产(同步)
- 在一个线程进行生产或消费时,其余线程不能再进行生产或消费(互斥)
/* items代表缓冲区已经使用的资源数, spaces代表缓冲区可用资源数 mutex代表互斥锁 buf[10] 代表缓冲区,其内容类型为item in、out代表第一个资源和最后一个资源 */ var items = 0, space = 10, mutex = 1; var in = 0, out = 0; item buf[10] = { NULL }; producer { while( true ) { wait( space ); // 等待缓冲区有空闲位置, 在使用PV操作时,条件变量需要在互斥锁之前 wait( mutex ); // 保证在product时不会有其他线程访问缓冲区 // product buf.push( item, in ); // 将新资源放到buf[in]位置 in = ( in + 1 ) % 10; signal( mutex ); // 唤醒的顺序可以不同 signal( items ); // 通知consumer缓冲区有资源可以取走 } } consumer { while( true ) { wait( items ); // 等待缓冲区有资源可以使用 wait( mutex ); // 保证在consume时不会有其他线程访问缓冲区 // consume buf.pop( out ); // 将buf[out]位置的的资源取走 out = ( out + 1 ) % 10; signal( mutex ); // 唤醒的顺序可以不同 signal( space ); // 通知缓冲区有空闲位置 } }
注:不能将线程里两个wait的顺序调换否则会出现死锁。
- 多生产者与多消费者问题:
桌子上有一个盘子,父亲往里面放苹果,母亲往盘子里放橘子,一个盘子里只能放一个水果:儿子吃橘子,女儿吃苹果,当且仅当有自己需要的水果时,子女们才可拿水果。
实现互斥的P操作一定要在实现同步的P操作之后,否则可能会引起死锁
3.9.5 管程
管程是由一组数据以及定义在这组数据上的对这组数据的操作组成的软件模块(跟类着对比理解),这组操作能初始化并改变管程中的数据和同步进程。
管程包含:
- 局部于管程的共享结构数据说明
- 对该数据结构操作的一组过程
- 对局部于管理的共享数据设置初始值的语句
管程的基本特性是:
- 局部于管程的数据只能被局部于管程的过程(方法)所访问
- 一个进程只有通过调用管程内的过程才能进入管程(方法)访问共享数据
- 每次仅允许一个进程在管程内执行某个内部过程
3.10 死锁
3.10.1 概念
死锁:各个进程相互等待对方手里的资源,导致都被阻塞
饥饿:由于长期无法等到需要的资源,进程无法向前推进的现象
死循环:一直无法跳出某个循环的现象
3.10.2 产生的条件
-
互斥。共享资源同时只能被一个线程访问。
-
占有且等待。一个进程因请求资源而阻塞时,对已获得的资源保持不放。
-
不可抢占。其他线程不能强行抢占线程的资源。
-
循环等待条件。线程T1在持有资源A1,同时在请求等待获取资源B,线程T2在持有资源B,然后在请求等待线程T1的持有资源,形成了交叉闭环申请。
总之,对不可剥夺的资源分配不合理,就有可能发生死锁。
3.10.3 死锁处理策略
为使系统不发生死锁,必须设法破坏产生死锁的四个必要条件之一,或者允许死锁产生, 但当死锁发生时能检测出死锁,并有能力实现恢复。
-
预防死锁:设置某些限制条件,破坏产生死锁的四个必要条件中的一个或几个,以防止发生死锁。
-
避免死锁:在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而避免死锁。
-
死锁的检测及解除:无需釆取任何限制性措施,允许进程在运行过程中发生死锁。通过系统的检测机构及时地检测出死锁的发生,然后釆取某种措施解除死锁。
预防死锁和避免死锁都属于事先预防策略,但预防死锁的限制条件比较严格,实现起来较为简单,但往往导致系统的效率低,资源利用率低;避免死锁的限制条件相对宽松,资源分配后需要通过算法来判断是否进入不安全状态,实现起来较为复杂。
死锁处理策略的比较
– | 资源分配策略 | 各种可能模式 | 主要优点 | 主要缺点 |
---|---|---|---|---|
死锁预防 | 保守,宁可资源闲置 | 一次请求所有资源,资 源剥夺,资源按序分配 适用于做突发式处理的进程,不必进行剥夺 | 效率低,进程初始化时间延长;剥夺次数过多;不便灵活申请新资源 | |
死锁避免 | 是”预防“和”检测“ 的折中(在运行时判断是否可能死锁) | 寻找可能的安全允许顺序 | 不必进行剥夺 | 必须知道将来的资源需求;进程不能被长时间阻塞 |
死锁检测 | 宽松,只要允许就分配资源 | 定期检查死锁是否已经发生 | 不延长进程初始化时间,允许对死锁进行现场处理 | 通过剥夺解除死锁,造成损失 |
3.10.4 死锁预防
设置某些限制条件,破坏产生死锁的4个必要条件中的一个或几个,以防止发生死锁
-
破坏互斥:
就是在系统里取消互斥。若资源不被一个进程独占使用,那么死锁是肯定不会发生的。但一般“互斥”条件是无法破坏的。
-
破坏不剥夺:
实现比较复杂,释放已获得的资源可能造成前一阶段工作的失效,反复地申请和释放资源会增加系统开销,降低系统吞吐量。这种方法常用于状态易于保存和恢复的资源,如 CPU的寄存器及内存资源,一般不能用于打印机之类的资源。
-
破坏请求与保持:
预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不把它投入运行。
缺点是资源有效利用率低,资源长期占用容易导致饥饿现象。 -
破坏循环等待:
3.10.5 死锁避免
顺序资源分配法。首先给系统中的资源编号,规定每个进程必须按编号递增的顺序请求资源,同类资源一次申请完。也就是说,只要进程提出申请分配资源 Ri 则该进程在以后的资源申请中就只能申请编号大于 Ri 的资源。
缺点:编号必须相对稳定,限制了新类型设备的增加;会发生作业使用资源的顺序与系统规定顺序不同的情况,造成资源的浪费。
系统安全状态
避免死锁的方法中,允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程; 否则,让进程等待。
所谓安全状态,是指系统能按某种进程推进顺序( P1, P2, …, Pn),为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺序地完成。此时称 P1, P2, …, Pn 为安全序列。如果系统无法找到一个安全序列,则称系统处于不安全状态。
4 内存管理
内存管理的功能∶
- 内存空间的分配与回收
- 地址转换
- 内存空间的扩充
- 存储保护
4.1 连续分配
4.1.1 单一连续分配
内存在此方式下分为系统区和用户区,系统区仅供操作系统使用,通常在低地址部分;用户区是为用户提供的、除系统区之外的内存空间。
这种方式无须进行内存保护。内存中只有一道程序,不会因为访问越界干扰其他程序。
缺点是只能用于单用户、单任务的操作系统中,存储器的利用率极低。
4.1.2 固定分区分配
固定分区分配是最简单的一种多道程序存储管理方式,它将用户内存空间划分为若干固定大小的区域,每个分区只装入一道作业。
固定分区分配的两种方法:
分区大小相等:用于利用一台计算机去控制多个相同对象的场合,缺乏灵活性。
分区大小不等:划分为多个较小的分区、适量的中等分区和少量大分区。
为便于内存分配,通常将分区按大小排队,并为之建立一张分区说明表,其中各表项包括每个分区的分区号、始址、大小及状态(是否已分配)。当有用户程序要装入时,便检索该表,以找到合适的分区给予分配并将其状态置为"已分配";未找到合适分区时,则拒绝为该用户程序分配内存。
空闲分区管理
- 空闲分区表:用来登记系统中的空闲分区(分区号、分区起始地址、分区大小及状态) 。
- 空闲分区链:前、后向链接指针用于把所有的空闲分区链接成一个双向链。当分区被分配出去以后,前、后向指针无意义。
加粗样式
回收内存
- 回收分区上邻接一个空闲分区,合并后首地址为空闲分区的首地址,大小为二者之和。
- 回收分区下邻接一个空闲分区,合并后首地址为回收分区的首地址,大小为二者之和。
- 回收分区上下邻接空闲分区,合并后首地址为上空闲分区的首地址,大小为三者之和。
- 回收分区不邻接空闲分区,这时在空闲分区表中新建一表项,并填写分区大小等信息。
这种分区方式存在两个问题∶
- 程序可能太大而放不进任何一个分区中,这时用户不得不使用覆盖技术来使用内存空间;
- 主存利用率低,当程序小于固定分区大小时,也占用一个完整的内存分区空间,这样分区内部就存在空间浪费,这种现象称为内部碎片。
4.1.3. 动态分区分配及分配策略
动态分区分配又称可变分区分配,是一种动态划分内存的分区方法。这种分区方法不预先划分内存,而是在进程装入内存时,根据进程的大小动态地建立分区, 并使分区的大小正好适合进程的需要。因此,系统中分区的大小和数目是可变的。
动态分区在开始分配时是很好的,但之后会导致内存中出现许多小的内存块。随着时间推移,内存中会产生越来越多的碎片,内存的利用率随之下降。这些小的内存块称为外部碎片,指在所有分区外的存储空间会变成越来越多的碎片。
克服外部碎片可以通过紧凑技术来解决,需要动态重定位寄存器的支持,且相对费时。
动态分区的分配策略:
- 首次适应(First Fit)算法。空闲分区以地址递增的次序链接。分配内存时顺序查找,找 到大小能满足要求的第一个空闲分区。
- 最佳适应(Best Fit)算法。空闲分区按容量递增的方式形成分区链,找到第一个能满足
要求的空闲分区。
缺点:每次都选最小的分区进行分配,会留下越来越多的、很小的、难以利用的内存块。因此这种方法会产生很多的外部碎片。 - 最坏适应(Worst Fit)算法。又称最大适应(Largest Fit)算法,空闲分区以容量递减的次序链接,找到第一个能满足要求的空闲分区,即挑选出最大的分区。
缺点:每次都选最大的分区进行分配,虽然可以让分配后留下的空闲区更大,更可用,但是这种方式会导致较大的连续空闲区被迅速用完。如果之后有“大进程”到达,就会没有内存分区可用。 - 邻近适应(Next Fit)算法。又称循环首次适应算法,由首次适应算法演变而成。不同之
处是,分配内存时从上次查找结束的位置开始继续查找。
首次适应算法每次都要从头查找,每次都需要检索低地址的小分区。但是这种规则也决定了当低地址部分有更小的分区可以满足需求时,会更有可能用到低地址部分的小分区,也会更有可能把高地址部分的大分区保留下来;
邻近适应算法的规则可能会导致无论低地址、高地址部分的空闲分区都有相同的概率被使用,也就导致了高地址部分的大分区更可能被使用,划分为小分区,最后导致无大分区可用。
4.2 非连续分配
4.2.1 分页管理
连续分配的缺点
- 固定分区分配:缺乏灵活性,会产生大量的内部碎片,内存的利用率很低。
- 动态分区分配:会产生很多外部碎片,虽然可以用“紧凑”技术来处理,但是“紧凑”的时间代价很高。
基本思想
- 内存空间分成若干个物理块,进程运行时,以块为单位进行内存申请;
- 用户程序的地址空间(逻辑地址)被划分成若干固定大小的区域,称为“页”;
- 页和块的大小相等,大小应该是2的整数幂(方便地址装换),从0开始编号;
逻辑地址结构:存于进程内
31…12 | 11…0 |
---|---|
页号 | 页内偏移量 |
页表寄存器
页表起始地址 | 页表长度 |
---|
页表:
页号 | 块号 |
---|
基本地址转换
在系统中通常设置有一个页表寄存器(PTR),用于存放页表的起始地址F(用于定位页表)和页表长度M(页表中有M个页表项)。设页面大小为L(物理地址和逻辑地址的页面大小相等),逻辑地址A到物理地址E的转化过程如下:
-
计算页号P(P=A/L)和页面偏移量(W=A%L)((P,W)用户进程内结构)
-
比较页号P和页面长度M,如果P大于等于M,则产生越界,否则继续执行
-
根据页表中的页号查找对应的物理块号b
-
计算E=b*L+W,得到物理地址E,根据此地址去方位内存进行数据的存取或者指令读取
具有快表的地址变换
快表(LTB):是一种访问速度比内存快很多的高速缓冲寄存器,原来存储当前访问的若干页表项。
先去快表内查询页表位置和页表长度,如果没有再去页表页表寄存器内查找,快表比页表寄存器查询速度快得多,如果直接命中快表会节省很多时间。
4.2.2 分段管理
段式管理方式按照用户进程中的自然段划分逻辑空间,如一用户进程由主程序,一个子程序,一段数据组成,可以分为3段,每段从0开始编址,并分配一段连续连续地址空间(段内要求连续,段间不要求连续)。每个进程都有一张逻辑空间与内存映射的段表。段号和段内偏移都必须有由用户显示提供,高级语言中由编译程序完成这个操作。
逻辑地址结构:存于进程内
31 … 16 | 15 … 0 |
---|---|
段号 | 段内偏移量 |
段表寄存器
段表始址 | 段表长度 |
---|
段表:
段号 | 段长 | 基址(本段所在内存地址首址) |
---|
地址转换
为了实现进程从逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器,用于存放段表始址 F 和段表长度 M。从逻辑地址 A 到物理地址 E 之间的地址变换过程如下∶
-
从逻辑地址A中取出前几位为段号 S,后几位为段内偏移量 W,注意在段式存储管理的计算中,逻辑地址一般以二进制数给出,而在页式存储管理中,逻辑地址一般以十进制数给出。
-
比较段号的段长度M,如果S大于等于M,则产生越界,否则继续执行
-
段表中段号S对应的段表项地址 = 段表始址F+段号S×段表项长度,取出该段表项的前几位得到段长C。若段内偏移量≥C,则产生越界中断,否则继续执行。可以看出,段表项实际上只有两部分,前几位是段长,后几位是始址。
-
取出段表项中该段的始址 b,计算E=b+W,用得到的物理地址E去访问内存。
资源共享与包保护
共享:A,B两个进程共享一段代码,则只需要将A,B进程内相关段号都指向该代码所在内存段进行了
保护:同样,只需要对段号(资源)相对应的内存进行保护
4.2.3 段页氏管理
分段和分页的比较
将这两种存储管理方法结合起来,便形成了段页式存储管理方式。
段页氏管理逻辑地址结构
在段页式系统中,进程的逻辑地址首先被分成若干逻辑段,每段有自己的段号,然后再将每一段分成若干个大小固定的页。对内存的管理方式仍然和分页管理方式一样,将其分成若干个和页面大小相同的存储块,对内存的分配以存储块为单位
一个进程中只有一个段表,但是有很多个页表,一个段表项对应一个页表
逻辑地址结构
31…16 | 15…12 | 11…0 |
---|---|---|
段号 | 段内页号 | 页内偏移量 |
- 段号的位数决定每个进程可以分成多少段(2^16)
- 页号的位数决定每个段有多少页 (2^4)
- 页内偏移量的位数决定内存块大小,页面大小 (2^12)
段表寄存器
段表始址 | 段表长度 |
---|
段表:
段号 | 段长 | 页表始址 |
---|
页表:
页号 | 块号 |
---|
地址转换
-
在被调进程的PCB中取出段表始址和段表长度,装入段表寄存器
-
段号与控制寄存器的页表长度比较,若页号大于等于段表长度,发生地址越界中断,停止调用,否则继续
-
由段号结合段表始址求出页表始址和页表大小
-
页号与段表的页表大小比较,若页号大于等于页表大小,发生地址越界中断,停止调用,否则继续
-
由页表始址结合段内页号求出存储块号
-
存储块号&页内地址,即得物理地址
在页式、段式存储管理中,为获得一条指令或数据,须两次访问内存;而段页式则须三次访问内存
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix