王道操作系统第二章

目录

第二章

1.1进程的定义,组成,组织形式以及特征

前言:为了方便操作系统管理,完成各程序并发执行,引入了进程以及进程实体得概念。系统为每一个运行得程序配置一个数据结构,称为进程控制块(PCB),用来描述进程得各种信息(如程序代码存放的位置)。PCB,进程段,数据段三部分就构成进程实体(进程映像)。一般进程实体简称进程,所谓得创建进程就是创建一个PCB,撤销进程,实质上就是撤销进程试实体中得PCB,PCB是CPU进程得唯一标识

传统经典定义
1):进程是程序的依次执行过程
2):进程是一个程序以及其数据在处理机上顺序发生得所有活动
3):进程是具有独立功能得程序再数据集合上运行得过程,它是系统进行资源分配和调度得一个基本单位
经典定义强调的是动态性

融入进程实体后的进程的定义
进程是进程实体在运行的过程中,系统进行分配资源的一个独立单位

组成

1):PCB

PCB其中又包括四部分内容

a):进程描述信息
其中包括标识符PID以及UID

进程标识符PID
当进程被创建的时候,操作系统会为该进程分配一个唯一的,不重复的ID,用于区分不同的进程

用户标识符UID:
用来表示当前j进程属于哪一个用户。

b):进程控制和管理信息
其中包含进程当前的状态以及进程的优先级

c):资源分配清单

d):处理机相关信息
当进程切换时,需要把进程当前的运行情况记录下的值保存在PCB中,如程序计数器的值表示当前程序执行到了哪一步

2):程序段
程序代码是存放在程序段中的,最终CPU执行的程序指令,也来源于此。

3):数据段:
程序运行时使用,产生的运算数据,以及定义的变量等,都放在数据段中。

组织方式:
进程之间的组织形式可以分为按照链接的形式,索引的形式。
1):链接方式:
按照进程队列状态将PCB分为多个队列,操作系统持有指向各个队列的指针
在这里插入图片描述

2):索引方式:在这里插入图片描述

根据进程状态的不同,建立几张索引表,操作系统持有指向各个索引表的指针

指针的分类
1):执行指针
指向当前正在运行的程序

2):就绪队列指针
指向就绪状态的进程,优先级高的进程,会排在队头

3):阻塞队列指针
指向阻塞状态的进程

进程的特征:

1):动态性:进程是程序的一次执行过程,是动态的产生,变化,消亡的

2):并发性:内存中有多个进程实体,各进程可以并发执行

3):独立性:进程是独立运行,独立获得资源,独立接受调度得基本单位

4):异步性:各进程按照各自独立的,不可预知的速度向前推进,操作系统要提供“进程同步机制”来解决异步问题

5):独立性:进程是独立运行,独立获得资源,独立接受调度得基本单位

6):结构性:每一个进程都会配置一个PCB。结构上看,进程由PCB,程序段,数据段组成

小结
在这里插入图片描述

1.2进程的状态以及切换

PCB中有一个状态变量(state)来标记当前的进程处于什么状态。比如1表示创建态,2表示就绪态,3表示运行态。

状态分类:

1):运行状态:占有CPU,并在CPU上运行

2):就绪状态:已经具备运行的状态,但是由于没有空闲的CPU,而暂时不能运行。已经获得了除了CPU以外所需的资源,一旦获得CPU,就能立马进入运行状态.

3):阻塞状态:因等待某一事件而暂时不能运行,如等待操作系统分配打印机,等待读磁盘操作结果。CPU是计算机中最昂贵的部件,为了提高CPU的利用率,需要先将其他进程需要的资源分配到位,才能获得CPU的服务。

4):创建状态:操作系统为进程分配所需的内存资源,并为其创建初始化的PCB(包括为进程分配的PID)

5):终止状态:程序结束运行,需要撤销进程。操作系统需要完成撤销进程的相关工作。完成分配给进程的资源回收,撤销进程PCB等工作

状态之间相互转换:

1):就绪态–>运行态:进程被调用

2):运行态–>阻塞态:进程用”系统调用“的方式请求某种系统资源,或者请求等待某个事件发生,阻塞态是程序自身做出的自主行为.

3):运行态–>就绪态:时间片到,处理机就会被抢占

4):阻塞态–>就绪态:申请的资源被分配,或者等待的事件发生,不是进程自身能控制的,是一种被动行为

小结:
在这里插入图片描述

1.3 进程控制

基本概念:

1):什么是进程控制:

进程主要功能是对系统中所有进程实施有效的管理,它具有创建新进程,撤销已有进程,实现进程转换等功能

2):如何实现进程控制

—>用“原语”实现-
1):原语
:用原语实现进程控制,原语的特点是执行期间一气呵成,不允许中断,这种不可中断的操作即原子操作

2):原语采用“关原语指令”和“开原语指令”实现
在操作系统执行关指令与开指令之间,操作系统会关闭中断指令的例行检查

3):开关原语指令必须只能在核心态下执行的特权指令

4):原语需要实现的功能:

①:更新PCB的信息(如修改进程状态的标识,将运行环境保存到PCB,从PCB恢复运行环境)

a:所有进程控制原语一定会修改进程状态标志

b:剥夺当前运行进程的CPU,必定需要保存其运行环境

c:某进程开始运行前,必定需要恢复前运行环境

②:将PCB插入合适的队列

③:分配/回收资源

在这里插入图片描述

进程控制相关的原语

1):进程的创建

创建原语的执行步骤

①:申请空白PCB

②:为新进程分配所需的资源

③:初始化PCB

④:将PCB插入就绪队列

引起进程创建的事件

用户登录:分时系统中,用户登录成功,系统会为其建立一个新的进程

作业调度:多道批处理系统中,有新的作业存入内存时,会为其建立一个新的进程

提供服务:用户向操作系统提出某些请求的时候,会新建一个进程处理该请求

应用请求:由用户进程主动请求创建一个子进程

2):进程的终止

终止原语的执行步骤

①:从PCB集合找到终止进程的PCB

②:若进程正在运行,立即剥夺CPU,将CPU分配给其他进程

③:终止其所有子进程

④:将该进程拥有的所有资源归还给父进程或操作系统

⑤:删除PCB

引起进程终止的事件

①:正常结束

②:异常结束

③:外界干预

3):进程的阻塞

阻塞原语的执行步骤

①:找到要阻塞的进程对应的PCB

②:保护进程运行现场,将PCB状态信息,设置为“阻塞态”,暂时停止进程运行

③:将PCB插入相应事件的等待队列

引起进程阻塞的事件:

①:需要等待系统分配某种资源

②:需要等待相互协作的其他进程完成工作返回结果

4):进程的唤醒

唤醒原语的执行步骤:

①:事件等待队列中找到PCB

②:将PCB从等待队列移除,设置进程为就绪态

③:将PCB插入就绪队列,等待被调度

引起进程唤醒的事件

①:等待的事件发生

进程的阻塞与唤醒是一对的,流程的阻塞肯定伴随着需要唤醒

5):进程的切换

切换原语的执行步骤

①:将运行环境信息存入PCB

②:PCB移入相应队列

③:选择另一个进程进行,并更新其PCB

④:根据PCB恢复新进程所需的运行环境

引起进程切换的事件

①:当前时间片到

②:有更为优先级的进程到达

③:当前进程主动阻塞

小结:
在这里插入图片描述

1.4 进程通信

概念
进程通信就是进程之间的信息交换
进程是分配系统资源的单位,因此各进程拥有的内存地址空间相互独立
为了保证安全,进程是不允许直接访问问另一个进程的内存地址的

1):共享存储
共享存储有两种形式

①:基于数据结构的共享
比如共享空间里和只能放一个长度为10的数组,这种共享方式速度慢,限制多。是一种低级的通信方式

②:基于存储区的共享
两个进程对共享空间的访问必须是互斥的(互斥访问通过操作系统提供的工具实现的)
在内存中画出一块共享存储区,数据的形式,存放位置都由进程控制,而不是操作系统

2):消息传递
概念:
进程间数据交换以格式化信息为单位,进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换

消息传递有两种形式

①:直接通信形式
将消息直接挂在接受进程的信息缓冲队列里

②:间接通信方式
消息要先发送到中间实体(信箱)中,因此也称为“信箱通信方式”

发送的消息包括消息头以及消息体–消息头:发送进程ID,接收进程ID,消息类型,消息长度等格式化的信息(计算机网络所发送的“报文”就是一种格式化的消息)

管道通信

概念:
“管道”是指用于连续读写进程的一个共享文件。又名pipe文件。其实就是在内存中一个大小固定的缓冲区

特点:
1):管道只能采用半双工通信–:某一段时间内只能实现单向的传递,如果要实现双向同时传输,则需要设置两个管道

2):各进程要互斥的访问管道

3):数据以字符流写入到管道中,当管道写满时,写进程write()系统调用会被阻塞,等待读进程将数据读走。当管道中的数据被全部取走变空后,此时读进程read()x系统调用将被阻塞

4):没有写满,就不允许读。没有读空,就不允许写

5):写满了,就无法再写,读空了,无法再读。

6):数据一旦被读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则可能会出现读错误的情况

小结:
在这里插入图片描述

1.5 线程,多线程模型

有的进程需要同时做很多事情,但是传统的进程只能串行的执行一系列的事情,为此引入了线程的概念,来增加并发度

背景
1):进程是程序的一次执行,但这些进程内所需要实现的功能不可能由一个进程顺序执行就能完成的。比如在QQ一边视频语音,一边文字聊天,一边在传文件。传统的进程只能串行的执行一系列的程序。所以此时就引入线程,增加并发度
2):传统的进程是程序执行流的最小单位,引入线程后,线程便是程序执行流的最小单位,以及CPU基本执行单位。
引入线程后,进程是除了CPU之外的系统资源的分配单位(如打印机,内存地址都是分配给进程的)

1):引入线程后的变化

①:资源分配调度方面
在引入线程之前,进程是资源分配,调度的基本单位
在引入线程之后,线程是资源分配,调度的基本单位

②: 并发性
传统进程机制中,只能进程间并发
引入线程之后,各线程之间也能进行并发,提高了并发度

③:系统开销
传统进程之间的并发,需要切换进程的运行环境,系统开销很大
线程间并发,如果是同一进程之间的线程切换,则不需要切换进程环境,系统开销小
引入线程之后,并发所带来的系统开销减小

2):线程有哪些重要的属性

①:线程是处理机调度的基本单位

②:多核CPU计算机中,各个线程可占用不同的CPU

③:每一个线程都有一个线程ID,线程控制块(PCB)

④:线程也有就绪,阻塞,运行三种基本状态

⑤:线程几乎不拥有系统资源(进程拥有系统资源,线程借用进程的)

⑥:由于共享内存地址空间,同一线程中的线程间通信甚至无需系统干预

⑦:同一进程内线程切换,不会引起进程切换

⑧:不同进程之间的线程切换,会引起进程切换

⑨:切换同进程内的线程,系统开销很小

3):线程实现的方式
线程实现的方式由用户级线程以及内核级线程。用户级线程是用户通过线程库实现的,而操作系统实际进行处理的是内核级线程。用户级线程与内核级线程之间的关系是,用户级线程需要映射到内核级线程,然后操作系统执行内核级线程。

①:用户级线程

a):用户级线程由应用程序通过线程库实现,所有的线程工作都是由应用程序来控制以及管理(包括线程切换),在用户态下就能完成,无需操作系统干预

b):用户视角看到的线程

②:内核级线程

a):内核级线程管理工作由操作系统内核完成,线程调度,切换等工作都由内核负责,因此内核级线程的切换需要在核心态的下才能完成

b):操作系统只“看得见”内核级线程,因此只有内核级线程才是处理机分配的基本单位

c):操作系统视角看到的线程

在这里插入图片描述

4):多线程模型
多线程模型,分为多对一,一对一,多对多模型。

①:多对一模型:
多个用户级线程映射到一个内核级线程,每个用户进程只对应一个内核级线程

优点
用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高

缺点:
当一个用户级线程被阻塞后,整个进程都会被阻塞(用户级线程阻塞后,连带唯一的内核级线程也会被阻塞),并发度不高。多个线程不可以在多核处理机上并发执行

②:一对一模型
一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程相同数量的内核级线程

优点
当一个用户级线程被阻塞后,别的线程可以继续执行,并发能力强。多线程可以在多核处理机上并行执行

缺点
一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态。因此线程管理成本大,开销大

③:多对多模型
n个用户级线程映射到m个内核级线程(n>m)。每个用户进程对应m个内核级线程

特点:
克服了多对一并发度不高的问题,也克服了一对一,一个用户级进程占用太多内核级线程,系统开销太大的问题

小结:
在这里插入图片描述

2.1处理机的概念,层次

基本概念:
1):当有一对任务要处理,但由于资源有限,这些事情没办法同时执行,这就需要确定某种规则来决定这些任务的顺序,这就是“调度”研究的问题

2):处理机调度,就是那个就绪队列中按照一定的算法选择一个进程并将处理机分配给它运行,以实现进程的并发执行

处理机调度得三个层次

①:高级调度(作业调度)

a):按照一定的职责从外存上处于后备队列中的作业挑选一个作业,给他们分配必要的资源,并建立相应的进程(建立PCB),促使他们获得竞争处理机的权利

b):高级调度是辅存(外存)与内存之间的调度,每个作业只调入一次,调出一次。作业调入的时候会建立PCB,作业调出的时候才撤销PCB,高级调度主要是指调入的问题,因为只有调入的实际由操作系统来决定,但调出的时机必须要作业完成才调出

②:中级调度(内存调度)

a):引入了虚拟存储技术后,可将暂时不能运行的进程调至外存等待,等它重新具备了运行条件且内存又稍有空闲时,再重新调入内存

b):这么做的目的在于提高内存的利用率,和系统吞吐量

c):暂时调到外存的进程状态为挂起状态,值得注意的是,PCB并不会一起调到外存,而是会常驻于内存,PCB户记录进程数据在外存中的存放位置,进程状态等信息,操作系用通过内存中的PCB保持对各个内存的监控,管理。被挂起的进程PCB会被放到挂起队列中

d):中级调度,就是决定哪一个挂起的进程重新调入到内存中

③:低级调度(进程调度)
就是按照某种算法从就绪队列中选择一个进程为其分配处理器

特点
1):进程调度其主要任务时按照某种算法和策略从就绪队列中选取一个进程,将处理机分配给它

2):进程调度是处理机最基本的一种调度,一般的操作系统中必须配备进程调度

3):进程调度是为了并发,一般调用频率也很高,几十毫秒一次

三个层次调度的联系,对比

在这里插入图片描述
高级调度与中级调度的区别
1):高级调度与中级调度都是从外存调到内存。但是高级调度考虑的是作业创建与结束时如何调度的问题,而中级调度是在进程被挂起时,如何调度进内存的问题。
2):一个作业的创建只会经历一次,所以高级调度在作业的整个生命周期中,也只是会出现一次。
3):一个作业因内存不足,而被挂起的次数会比较多,所以中级调度在作业的整个生命周期中,会出现多次。

补充知识

进程的“挂起态”,暂时调到外存等待的进程状态称为挂起状态

七状态模型:

在这里插入图片描述
挂起态与阻塞态的区别

挂起态与阻塞态都是暂时不能获得CPU的服务,但是挂起态是因为内存不够而被放在外存的。而阻塞态,是依然在内存中的。

小结:
在这里插入图片描述

2.2进程调度的时间,切换与时机

1)时机:

①:什么时候需要进程调度:

a):当前运行得进程主动放弃处理机–

Ⅰ:正常终止

Ⅱ:运行的过程中遇到异常终止

Ⅲ:进程主动请求阻塞(等待I/O)

b):当前得进程被动得放弃处理机
Ⅰ:进程时间片用完

Ⅱ:有更紧急得事需要处理

Ⅲ:有更高级的进程进入就绪队列

②:什么时候不需要进程调度

①:在处理中断得过程中,中断处理过程复杂,与硬件密切相关,很难做到在中断处理的过程中进行进程切换

②:进程在操作系统内核程序临界区中

这里有几个名词需要注意的:

临界资源
一个时间段内只允许一个进程使用的资源,各进程需要互斥的访问临界资源

临界区:
访问临界资源的那段代码

内核程序临界区
c):一般是用来访问某种内核数据结构的,比如进程的就绪队列(由各就绪进程的PCB组成)

b):当一个进程处于内核程序临界区,而内核程序临界区在访问就绪队列之前,就绪队列会上锁。如果进程还没有退出临界区(还没解锁),就进行进程调度,但是进程调度相关程序也需要访问就绪队列,但此时就绪队列被锁住了,因此无法顺利进行进程调度了

c):内核程序临界区访问的l临界资源如果不尽快释放的话,极可能影响到操作系统内核的其他管理工作,因此在访问内核程序临界区期间不能进行调度与切换

(需要注意的是,内核临界资源,当被一个进程访问的时候,如果此时切换到另一个进程,就会对操作系统的管理工作产生影响,因为内核临界资源只允许一个进程使用,在该进程使用的时候是不允许其他进程使用的。而此时另外一个进程在运行的过程中,几乎都会使用该临界资源,没有该内核临界资源,进程是没办法正常运行的。但是这个临界资源已经被上锁了,只能允许前面一个进程使用。那么此时另外一个进程去请求该资源就会出现问题。所以在一个进程使用内核临界资源的时候,是不允许切换到另外一个进程的,需要一气呵成的使用完,将该内核临界释放后,才能进行切换到另外一个进程)

普通的临界资源是可以进行进程之间的调度。比如在打印机完成之前,进程会一直处于临界区,临界资源不会解锁,但打印机又是慢速设备,如果一直不允许进程调度的话就会导致CPU一致空闲
普通临界区访问的临界资源不会直接影响到操作系统的管理工作,因此在访问管理临界区的时可以进行调度与切换

③:在原子操作得过程中,原子操作不可以中断,需要一气呵成

2):切换与过程

“狭义的调度”与切换得区别

①:狭义的进程调度指的是从就绪队列中选中一个要运行的进程(这个进程可以是刚刚被暂停的进程,也可能是另一个进程,后一种情况就需要进程切换)

②:进程切换指的是一个进程让出处理机,由另一个进程占用处理机的过程

③:广义的进程切换指的是进程选择和进程切换两个步骤。

④:注意:如果频繁的进程切换,调度,必然会使整个系统的效率降低,使系统大部分事件都花在了进程切换上,而真正的执行进程的时间就减少了

进程切换得过程需要什么

①:需要保存当前进程的运行状态和信息

②:需要为下一个进程配置资源

3):方式

非剥夺调度方式(非抢占式):只允许进程主动的放弃处理机,在运行的过程中,如果由更为紧急的任务到达,当前的进程依然会占用着处理机,直至该进程主动的阻塞或运行结束

剥夺调度方式(抢占式):当一个进程在处理机上运行得时候,如果由一个更为重要或者紧急的任务到达,z则立即暂停当前的进程,将处理机分配给那个更为紧急的任务

小结:
在这里插入图片描述

2.3调度算法的评价指标:

1):CPU利用率:是指CPU工作的时间占总时间的比率

2):系统吞吐量:单位时间内完成任务的数量

3):周转时间

①:周转时间,平均周转时间
周转时间
作业完成时间-作业提交时间–在并发的情况下涉及多个进程交替运行的情况,这就增加了周转的时间

平均周转时间:
各作业周转时间之和/作业数量

②:带权周转时间,平均带权周转时间

计算带权周转时间的方式:

方式一:
作业周转时间/作业实际运行的时间

方式二
(时间完成时间-作业提交时间)/作业实际运作时间

③:平均带权周转时间:
各作业带权周转时间之和/作业数

周转时间,指的是从作业提交给系统开始,到作业完成为止的这段时间间隔

周转时间包括四个部分:

a):作业在外存后被队列里等待调度作业得时间(高级调度)

b):进程在就绪队列上等待进程调度的时间(低级调度)

c):进程在CPU上执行的时间

d):进程的等待I/O操作完成的时间

4):等待时间:

①:指的使进程或者说作业处于处理机等待时间之和,等待时间越短,用户满意度越低

②:对于进程来说,等待时间是指等待被处理机服务的时间之和,在等待I/Ow完成的期间其实也是在被服务的期间,所以不计入等待时间

③:对于作业来说,不仅要考虑建立进程后等待的时间,也要考虑在外存后被队列中的等待时间

5):响应时间:
指用户提交请求到首次被响应所用的时间

2.4 FCFS,SJF,HRRN调度算法

算法学习思路可以从以下几个问题层面来考虑

①:算法思想(基于什么目的或者说问题需要这么一个调度算法来实现)

②:算法规则(该算法如何去实现的)

③:这种调度算法是用于作业调度还是进程调度

④:抢占式,非抢占式

⑤:优点以及缺点

⑥:是否会导致饥饿(某进程/作业长期得不到服务)

1):先来先服务算法(FCFS):
学习思路
算法思想:
主要从公平的角度考虑(类似于生活中的排队买东西)

算法规则:
按照进程/作业到达的先后顺序进行服务

这种调度算法是用于作业调度还是进程调度
用于作业调度时,考虑的是那个作业先到达后备队列,用于进程调度的时候,考虑的是哪个进程先到达就绪队列

是抢占式还是非抢占式:
非抢占式的算法

优点
公平,算法容易实现

缺点
排在长作业(进程)后面的短作业需要等待很长的时间,带权周转时间很大,对于短作业用户不好。即FCFS对于长作业有利对于短作业不利

是否会导致饥饿:
不会

在这里插入图片描述
2):短作业优先(SJF)

算法学习思路

算法思想:
追求最少的平均等待时间,最少的平均周转时间,最少平均带权周转时间

算法规则:
最短作业/进程优先得到服务,(最短,指的是服务时间最短)

这种调度算法是用于作业调度还是进程调度
既可用于作业调度,也可用于进程调度,用于进程调度成为短进程优先算法(SPF :shorted process First)

是抢占式还是非抢占式:
SJF与SPF是非抢占式的算法,但是也有抢占式的算法–最短剩余时间优先算法
在这里插入图片描述在这里插入图片描述

需要注意的是:只有新进程/新作业进来的时候,调度算法才会看哪个进程/作业的剩余时间是否更短。

优点
可以获得最短平均等待时间,平均周转时间,平均带权周转时间

缺点
不公平,对于短作业有利,对于长作业不利,可能产生饥饿的现象。

是否会导致饥饿:
会导致,如果源源不断由短作业/进程的到来,可能就会使得长作业/进程得不到服务

在这里插入图片描述

3):高响应比优先(HRRN)

算法学习思路

算法思想:
要综合考虑作业/进程的等待时间和要求服务的时间

算法规则:
在每次调度时,先计算各个作业/进程的响应比,选择响应比最高的作业/进程进行服务

响应比的计算方式
(等待时间+要求服务的时间)/要求服务的时间

这种调度算法是用于作业调度还是进程调度
既可以用于作业调度,也可以用于进程调度

是抢占式还是非抢占式:
非抢占式,只有当前的进程/作业主动的放弃处理机的时候,才需要调度,计算响应比

优点与缺点
①:综合考虑了等待时间和运行时间(要求被服务的时间)

②:等待时间相同的时候,要求服务时间短的进程/作业优先(SJF优先)

③:要求服务时间相同时,等待时间长的优先(FCFS优点)

缺点
不公平,对于短作业有利,对于长作业不利,可能产生饥饿的现象。

是否会导致饥饿:
不会

在这里插入图片描述

2.5时间片轮转,优先级,多级反馈队列

1):优先级:

算法学习思路

算法思想:
随着计算机的发展,特别是实时操作系统出现,越来越多的应用场景需要根据任务的紧急程度来决定优先顺序

算法规则:
每个作业/进程都设置由各自的优先级,调度时选择优先级最高的进程/作业

这种调度算法是用于作业调度还是进程调度
可以应用于作业调度以及进程调度

是抢占式还是非抢占式:
抢占式与非抢占式都有
抢占式
在这里插入图片描述
非抢占式:
在这里插入图片描述

优点
用优先级区分紧急程度,重要程度,适用于实时操作系统,可灵活的调整各作业/进程的紧急程度

缺点
若源源不断有高级进程或作业进来,就可能导致低级进程饥饿

是否会导致饥饿:

如何合理的设置各进程的优先级
①:系统进程高于用户进程

②:前台进程高于后台进程

③:操作系统偏好于I/O型进程(也称繁忙型进程)
a):与I/O型进程相对的是计算型进程(或称CPU繁忙型)

b):I/O设备可以与CPU可以并行工作,如果优先让I/O繁忙型进程优先执行的话,则越可能让I/O设备尽早地工作。则资源利用率,系统吞吐量都会上升

根据优先级是否可以动态改变,可以将优先级类型分为静态优先级以及动态优先级

静态优先级:
当进程创建时就被确认了,之后一直不变

动态优先级
创建进城的时候有一个初始值,之后会根据情况动态的调整优先级

如果采用的是动态优先,什么时候可以调整

①:可以从追求公平,提升资源利用率等角度考虑
如果某进程再就绪队列中等待了很长时间,则可以适当的提升其优先级

②:如果某进程占用处理机很长时间,则可适当降低其优先级

③:如果发现一个进程频繁的进行I/O操作,则可以适当提升其优先级

2):时间片轮转

算法思想:
公平的,轮流的为各个进程服务,让每一个进程在一定时间间隔内都可以得到响应

算法规则:
按照各进程到达就绪队列的顺序,轮流让各个进程执行一个时间片,若进程未在一个时间片内执行完,则剥夺处理机,将进程重新放到就绪队列排队

这种调度算法是用于作业调度还是进程调度
用于进程调度(只有作业放入内存建立了相应的进程后,才能被分配处理机时间片)

是抢占式还是非抢占式:
若进程在时间片内未运行完毕,将会被剥夺处理机使用权,因此是抢占式算法

优点
公平,响应快,适用于分时操作系统

缺点
由于高频率的进程切换,因此有一定的开销,不区分任务的紧急程度

是否会导致饥饿:
不会

需要注意的:
1):如果时间片太大,使得每一个进程都可以在一个时间片内完成,则时间片轮转电镀算法就退化成先来先服务算法,并且会增大进程响应时间,因此时间片不能太大

2):另一方面,j进程调度,切换是有s时间代价的(保存和恢复运行环境),如果时间片太小,会导致进程切换频繁,系统会花大量的时间来处理进程切换,从而导致实际用于进程执行的时间比例减少。

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

多级反馈队列

算法思想:
对其他调度算法的折中权衡

算法规则:
1):设置多级就绪队列,各级队列从高到低,时间片从小到大

2):新进程到达时先进入第一级队列,按FCFS原则排队等待分配时间片,若时间片用完进程还没有结束,则进程就进入到下一级队列队尾。如果此时已经是在最下层的队列,则重新放回该队列的对尾

3):只有第K级队列为空的时候,才会为K+1级进程分配时间片用于进程调度

这种调度算法是用于作业调度还是进程调度
用于进程调度

是抢占式还是非抢占式:
抢占式的算法,在K级队列的进程运行过程中,若更上级的队列(k+1)中进入了一个新进程。则由于新进程处于优先级更高的队列中,因此新进程会抢占处理机。原来运行的进程放回K级队列队尾

优点
对各类型的进程相对公平(FCFS优点),每个新到达的进程都可以很快的得到响应(RR的优点),短进程只用较少的时间就完成(SPE的优点),不必实现估计进程的运行时间(避免用户作假),可灵活的调整的对各类进程的偏好的进程。比如CPU密集型进程,I/O密集型进程

是否会导致饥饿:

在这里插入图片描述

3.1进程同步,互斥

进程同步
同步亦称直接制约关系,它是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调他们的工作次序而产生的制约关系。进程间的直接制约关系就是源于他们之间的相互合作

进程互斥:
一段时间内只允许一个进程使用的资源就叫做临界资源,
对于临界资源的访问必须互斥的进行,互斥亦称间接制约关系。进程互斥指当进程访问某一临界资源的时候,另一个进程也想要访问该临界资源的时候需要等待。当访问临界资源的进程结束访问的时候,另一个进程才能够进行访问

对于临界资源的访问,可以在逻辑上分为四个部分
1)进入区
负责检查是否可进入临界区,若可以进入,则应设置正在访问临界资源的标志(可理解为上锁),以防止其他进程同时进入临界区

2)临界区
实际访问临界资源的那段实际操作设备的指令,比如对打印机发出的写操作指令

3)退出区
负责接触正在访问临界资源的标志(解锁)

4)剩余区
做其他处理

需要注意的三个点:
1):临界区是进程中访问临界资源的那段代码

2):进入区和退出区是负责实现互斥的代码

3):临界区亦称临界段

为了实现对临界资源的互斥访问,同时保证系统整体的性能,需要遵循四个原则

1)空闲让进(临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区)

2)忙则等待(当已经有一个进程访问该临界区时,其他试图进入临界区的进程必须等待)

3)有限等待(对请求访问的进程,应保证能在有限的时间内能进入临界区(保证不会饥额))

4)让权等待(当进程不能进入临界区时,应立即释放处理机,防止进程忙等待)

小结:
在这里插入图片描述

3.2进程互斥的软件实现方式

基于软件实现的进程互斥

1)单标志法:
算法思想是:两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程,也就是说每个进入临界区的权限只能被另一个进程赋予

在这里插入图片描述
在这里插入图片描述
2):双标志先检查法
算法思想:设置一个布尔型数组flag[],数组中各个元素用来标志各进程想进入临界区的意愿,比如flag[0]=true ,意味着0号进程p0现在想要进入临界区。每个进程在进入临界区之前会检查有没有其他进程想进入临界区。如果没有就把自身对应的标志flag[i]设为true,之后开始访问临界区

在这里插入图片描述
此时有一个问题
若按照1,5,2,6,3,7的顺序执行,P0和P1将会同时访问临界区。因此双标志先检查法的主要问题是:违反“忙则等待”的原则。原因在于进入区的“检查”和上锁两个处理不是一气呵成的,“检查后”,“上锁”前进程可能发生切换。

3)双标志后检查法
算法思想:双标志后检查的改版,前一个算法的问题是先“检查”后上锁。但是这两个操作又无法实现一气呵成,因此导致了两个进程同时进入临界区的问题。因此,人们想到了先“上锁”,后“检查”的方法,来避免上述的问题

在这里插入图片描述
这个算法同时存在一个问题
若执行顺序是按照1,5,2,6…顺序执行的,那么P0和·P1都无法进入临界区,因此,双标志后检查法虽然解决了“忙则等待”的原则,但是又违背了“空闲让进”和”有限等待“的原则。会因各进程长期无法访问临界资源而产生”饥饿“现象。

4)Peterson算法
算法思想:双标志后检查法中,两个进程都争着进入临界区,但是谁也不让谁,最后导致谁也不能进入临界区。peterson算法的思想就是,如果双方都争着想进入资源区,那可以让进程尝试主动让对方先使用临界区

实现:设置一个表示自己是否有意愿使用资源的值,设置一个自己是否已经谦让的值。检查时,就检查对方是否想使用资源,以及自己是否谦让了。如果都满足,就让给对方。如果只要其中一个是不满足的,就自己使用临界资源。

在这里插入图片描述

Peterson遵循用软件方法解决了进程互斥的问题,遵循了空闲让进,忙则等待,有限等待的原则,但是依然未遵循让权等待的原则(当让权后,依然会进入到while循环忙等待的情况)

小结:

在这里插入图片描述

3.3进程互斥硬件互斥方法

1)中断屏蔽方法:
算法思想:利用“开/关中断指令”实现(与原语的实现原理相同,即在某进程开始访问临界区到结束访问为止都不允许被中断,也就不能发生进程切换,因此也不可能发生两个同时访问临界区的情况)
但是在多处理机上运行的时候,另外一个处理机上运行的程序B也可以访问这个临界区。所以这个互斥方法只适合单处理机。
在这里插入图片描述

优点:
简单,高效

缺点:
不适用于多处理机,只适用于操作系统系统内核进程,不适用于用户进程(因为开/关中断指令只能运行在内核态。这组指令如果能让用户随意使用很危险),这个只适用于当前处理机上才有效

2)TestAndSet(TS指令/TSL指令):
简称TS指令,也有地方称为TestAndSetLock指令,或者TSL指令

TSL指令是用硬件实现的,执行的过程中不允许被中断,只能一气呵成

在这里插入图片描述

若刚开始lock是false,则TSL返回的Old指为false,while循环条件不满足,直接跳过循环,进入临界区。若刚开始为lock是true,则执行TSL后old返回的指是true,while循环条件会满足,会一直循环,直到当前访问临界区的进程在退出区进行“解锁”
像比如软件实现方式,TSL指令吧“上锁”,“检查”两个步骤用硬件的方式变成一气呵成的操作。

优点:
实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞,适用于多处理机环境

缺点:
不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令。从而导致忙等

4)Swap指令(XCHG指令):
有的地方称为Exchange指令,或简称XCHG指令

特点
Swap指令是用硬件实现的,执行的过程中不允许中断,只能一气呵成的执行完毕

在这里插入图片描述

逻辑上来看Swap和TSL并没有大的区别,都是先记录下此时临界区是否已经上锁(记录在old变量上),再将上锁标记lock设置为true,最后检查old,如果old为false则说明之前没有别的进程对临界区上锁,则可跳出循环,进入临界区

优点
实现简单,无需像软件实现方法那样严格检查是否会出现逻辑漏洞,适用于多处理机环境

缺点
不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环并执行TSL指令,从而导致“忙等”

小结:
在这里插入图片描述

3.4信号量机制:

1965年,荷兰学者Dijkstra提出了一种卓有成效得实现进程互斥,同步得方法–信号量机制。

特点
1)用户进程可以使用操作系统提供的一对原语l来对信号量进行操作,从而很方便的实现了进程互斥,进程同步得问题

2)信号量其实就是一个变量(可以是一个整数,也可以是更为复杂的记录型变量),可以用一个信号量来代表系统中某种资源的数量。比如,系统有一台打印机,就可以设置初值为1得信号量

3)一对原语:wait(S)原语和signal(S)原语,可以把原语理解为我们自己写的函数,函数名分别为wait和signal,括号里的信号量S就是函数调用时传入的一个参数

4)wait和signal原语常简称为P,V操作(来自荷兰语proberen和verhogon),因此有时被称为P(S),V(S),这对原语可用于实现系统资源的“申请”和“释放”

信号量机制类型分为两种
1)整型信号量
就是用一个整数代表系统中某种资源的数量
与普通整数变量的区别在于对信号量的操作只有三种:初始化,P操作,以及V操作

在这里插入图片描述
2)记录型信号量

即用记录型数据结构表示的信号量

在这里插入图片描述
注:
1)process中存放的是自行阻塞的进程,当需要的资源被释放的时候,里面被阻塞的进程会被逐渐解除阻塞

2)S.value的初值代表得是系统中某种资源的数量

3)对信号量S的一次P操作意味着进程请求一个单位的该类资源。因此需要执行S.value–(减一操作),表示现有空闲资源数减一,当S.value<0时表示该类资源已分配完毕,因此进程应调用block原语进行自我阻塞(当前运行的进程从运行状态切换到阻塞态),主动的放弃处理机,并插入该类资源的等待队列S.L中。该机制时遵循了“让权等待”原则,不会出现忙等的现象

4)对信号量S的一次V操作意味着进程释放一个单位的该类资源。因此需要S.value++,表示该类资源加1,若加1后仍是S.value<=0,表示依然有进程爱等待该类资源,因此应调用wakeup原语唤醒等待队列中的第一个进程(被唤醒的进程从阻塞态切换到运行态)

小结

在这里插入图片描述

3.5用信号量机制实现进程互斥,同步,前驱问题

实现进程同步
要让各并发进程按要求有序的推进

用信号量实现进程同步的步骤:
1):分析什么地方需要实现“同步关系”,即必须保证”一前一后“执行的两个·操作(或两句代码)

2)设置同步信号量S,初始值为0

3)在”前操作“之后执行V(S)

4)在”后操作“之前执行P(S)

思想:如果你在我之前操作会被阻塞,如果你阻塞了,我操作相关的操作结束后,我就会释放你。这样可以确保,我有些操作,是肯定在你之前的。这样就实现了同步关系。

在这里插入图片描述

实现进程互斥的步骤
1):分析并发进程的关键活动,划定临界区(如:对临界资源的访问就放在临界区)

2)设置mutex,初值为1(这里的mutex标记的是唯一能在临界资源区访问的进程数)

3)在临界区之前执行P(mutex)

4)在临界区之后执行V(mutex)

需要注意的是:对不同的l临界资源需要设置不同的互斥信号量

实现进程前驱关系的步骤:
1)要为每一对前驱关系各设置一个同步变量

2)在”前操作“之后对相应得同步变量执行一个V操作

3)在”后操作“之前对相应的同步变量执行一个P操作

在这里插入图片描述

小结

在这里插入图片描述

3.6生产者消费者问题

系统中有一组生产者进程和一组消费者进程,生产者每次生产一个产品放入缓冲区,消费者进程每次都从缓冲区取出一个产品进行消费。生产者与消费者共享一个初始为空,大小为N的缓冲区

特点
1)只有缓冲区没满时,生产者才能把产品放入到缓冲区,否则必须等待
这是同步关系,缓冲区满的时候,生产者需要等待消费者拿走产品

2)只有缓冲区不空的时候,消费者才能从中取出产品,否则只能等待
这是同步关系,缓冲区空的时候,消费者需要等待生产者生产出产品

3)缓冲区是临界资源,各进程必须互斥的访问

在这里插入图片描述
思考:消费者能否先考虑是否上锁,再然后考虑能否消费呢?
不能
,因为缓冲区都放满了产品后,empty为0,full为n。
生产者进程执行P(mutex)使mutex为0.再执行P(empty)。由于没有空闲的缓存区,因此生产者被阻塞。由于生产者阻塞,因此切换回消费者进程。消费者执行P(mutex),由于mutex是0,即生产者没有释放临界资源的锁,因此消费者也被阻塞。
这就造成了生产者等待消费者释放空闲缓冲区,而消费者又等待生产者释放临界区的情况,生产者与消费者相互等待对方唤醒。这就形成了死锁

因此实现互斥的操作一定要放在实现同步的P操作之后

生产者生产产品与消费者使用产品的步骤使放在p,v操作之外的。如果将此放入P,V操作之内,就会导致阻塞时间变长(生产者因为缓冲区都放满了产品。所以陷入阻塞,如果消费者将消费产品的步骤放在PV操作之内,那么在P,V内处理的时间就会变长,进而生产者需要等待更长的时间)

3.7多生产者,多消费者的问题

这个问题与生产者消费者问题有所不同的是:生产者消费者中,生产者们都是生产一种产品,而消费者只消费一种产品。而多生产者是生产多种产品(但是一种生产者只生产一种产品),多消费者是消费多种的产品(一个消费者只能消费一种产品)

例子:父亲生产橘子(一次只能生产一个),小明(儿子)消费橘子。母亲生产苹果,小芳(女儿)消费苹果。只有一个水果盘可以放水果,而一次只能在上面放一种。现在的情况是父亲在果盘上放了橘子后,母亲就无法在放苹果。只能等小明,或者小芳在果盘上取走并吃掉后,父亲或者母亲才能在果盘上继续放水果

在这里插入图片描述
这里即使不设置互斥变量mutex,也不会出现多个进程同时访问缓存区的情况:
主要是因为这里的缓存区大小只为1(盘子只能放入一份水果),如果缓存区的大小大于1,那么需要设置进程互斥变量,否则就可能出现两个进程对一个缓存区进行写操作,这样就会发生数据覆盖的问题

3.8吸烟者问题

假设系统有三个抽烟者进程和一个供应者进程。每个抽烟者不断地卷烟并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草,纸和胶水。三个抽烟者中,第一个拥有烟草,第二个拥有纸,第三个拥有胶水。供应者进程无限的供应这三种材料,供应者每次将材料放桌子上,拥有剩下两种材料的抽烟者卷一根烟并抽掉它,并给供应者一个信号告诉完成了。供应者就会将放另外两种材料在桌上,这个过程一直重复(让三个抽烟者轮流抽烟)

本质上也属于"生产者-消费者"问题

在这里插入图片描述

在这里插入图片描述

3.9读者,写者问题

有读者,写者两组并发进程,共享一个文件。当两个或两个以上进程同时访问共享数据时不会产生副作用,但若某个写进程和·其他进程(读进程和写进程)同时访问共享数据的时候可能导致数据不一致的错误。因此要求:
①允许多个读者可以同时对文件执行读操作
②只允许一个写者往文件里写数据
③任意写者在完成写工作的时候不允许其他写者和读者工作。
④写者执行工作前,应让其他读者和写者停止工作

在这个问题上,读者与写者之间需要进行互斥,写者与写者之间需要实现互斥。而读者与读者之间不需要互斥
在这里插入图片描述
只有读进程为0的时候,才会进行释放锁,如果在这段时间内,有源源不断地读进程近来,那么锁就无法被释放,写进程就一直拿不到锁进行数据的更新。

优化后:

在这里插入图片描述
当有写进程进来的时候,会对这个互斥访问变量进行上锁,但是会等前面的读进程执行完读的操作。而后面的读进程就会被阻塞。

核心思想,在于设计了一个count的计数器,如果计数器大于0,说明之前有读者进程了,那么也就进行了互斥上锁。此时再来其他读者进程,判断计数器大于0,就不需要加锁,直接访问。mutex是为了保证再判断count以及上锁两个步骤是原子性操作。w是为了保证写进程不会因为源源不断地读进程地到来而发生饥饿

3.10哲学家进餐问题

桌子上坐着五位哲学家,每一个哲学家面前有一根筷子,桌子中间是一碗米饭。哲学家倾注毕生的精力去进餐,哲学家在思考的时候,并不会影响其他人。只有当哲学家饥饿的时候 次啊会尝试拿起左右两根筷子(一根一根地拿起)。如果筷子在其他人手里,则需要等待。饥饿的哲学家只有当拿着两根筷子的时候才可以开始进餐,当进餐完毕后,继续思考

此时有一个问题

如果五位哲学家并发的执行,他们同时拿起左边的筷子,那么此时就会出现彼此都在等待对方释放右边的筷子,而自己却不会主动的释放手里的筷子,那么此时就会出现彼此之间相互等待,进而出现死锁的现象

解决方案

方案一:

可以对同时进餐的哲学家数量做一定的限制,让进餐的哲学家数量小于总共哲学家数量。那么其中必有一个可以拿到完整的筷子数进行进餐,等该哲学家进餐完毕后,就会释放筷子,剩下的哲学家就可以持有该筷子进行进餐。这样就避免了阻塞的情况

方案二

要求奇数号哲学家先拿左边的筷子,然后再拿右边的筷子。而偶数号的哲学家正好相反。用这种方法,就可以保证如果左右两边哲学家同时想要吃饭,那么其中一位哲学家拿起第一根筷子,另一个哲学家直接就进行了等待,避免了占用一根然后等待另一根的情况

3.11管程

1):为什么引入管程
①:使用信号量机制(P,V操作)容易出现编程困难,易出错。所以Brinch Hansen在1973年引入了“管程”的概念。使得程序员不需要再关注复杂的PV操作。

②:引入管程主要是为了更为方便的实现进程互斥和进程同步

2):管程的定义和特征
①:定义
管程是一种特殊的软件模块,分为四部分组成
a:局部于管程的共享数据结构说明
在代码上类似于类的定义,类里面有定义好的数据

b:对该数据结构进行操作的一组过程
这个过程也叫做“函数”,类似于类的方法

c:对局部于管程的共享数据设置初始值的字句
类似于类的初始化语句

d:管程有一个名字
类的名字

②:基本特征
a:局部于管程的数据只能被局部于管程的过程访问
b:一个进程只有通过调用管程内的过程才能进入管程访问共享数据
c:每次仅允许一个进程在管程内执行某个内部过程(函数方法)

3)扩展1:用管程来解决生产者消费者的问题
步骤:
a:需要在管程中定义共享数据(如生产者消费者问题的缓冲区)

b:需要在·管程中定义用于访问这些共享数据的入口,其实就是一些函数(如生产者消费者问题中,可以定义一个方法用于生产产品,定义一个方法用于消费产品)

c:这又通过特定的入口才能访问这些数据

d:管程中有很多“入口”,但是每次只能开放其中一个“入口”,并且只能让一个进程或者线程进入(这种互斥特性是由编译器实现的)

e:可在管程中设置条件变量及等待/唤醒操作以解决同步问题,可以上一个进程或者线程在条件变量上等待(此时,该进程应该先释放管程的使用权,也就是让出”入口“),可以通过唤醒操作将等待在条件变量上的进程和线程唤醒


这是利用伪代码实现的管程

小结:
在这里插入图片描述

4.1死锁

什么是死锁:
在并发的环境下,各进程因竞争资源而造成相互等待对方手里的资源,导致进程都阻塞,都无法向前推进的现象。这就是死锁,发生死锁后,若没有外力涉入,将无法向前推进。

进程死锁,饥饿,死循环的区别

饥饿:表示是进程长期得不到自己想要的资源,某进程无法向前推进的现象。
死循环:某进程执行一直跳不出某个循环的现象,有时是程序逻辑BUG导致的,有时是程序员故意设计的
死锁:多个进程争夺有限的资源,拥有一部分资源的进程等待另外的进程释放资源,而对方也是在等待。

在这里插入图片描述

死锁产生的必要条件:

1):只有对必须互斥使用的资源的争夺才能发生死锁,像内存,扬声器这种可以同时让多个进程使用的资源是不会导致死锁的

2):不可剥夺条件,在进程没有使用完资源之前,不能由其他进程夺取,只能主动释放

3):请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又被其他进程占有,此时请求进程被阻塞,但又对自己已有的资源保持不放

4):循环等待条件:存在一个资源循环等待请求链,链中的每一个进程以获得资源同时被下一个进程所请求

什么时候会产生死锁
1):对不可剥夺的系统资源争夺可能会发生死锁

2):进程推进顺序非法,请求和释放资源的顺序不当,也同样会产生死锁

3):信号量的使用不当也会产生死锁,如生产者-消费者问题中,如果实现互斥的P操作在实现同步的P操作之前就会产生死锁的现象

死锁的处理策略:

1):破坏死锁:破坏死锁产生的四个必要条件中得一个或几个

2):避免死锁。用某种方法防止系统进入不安全状态,从而避免死锁(银行家算法)

3):死锁得检测和解除。允许死锁的发生,但是操作系统会负责检测死锁的发生,然后采取某种方法解除死锁

小结:
在这里插入图片描述

4.2死锁得处理策略

不允许死锁发生的情况下,有两种死锁的处理策略。一种是静态策略–预防死锁。一种是动态策略–避免死锁。

1):静态策略–预防死锁
预防死锁的四种方式:1:破坏互斥条件。2:破环不剥夺条件。3:破坏请求和保持条件。4:破坏等待条件

①:破坏互斥条件
a:只有对必须互斥使用得资源进行争夺才会产生死锁

b:如果将只能互斥使用的资源改造为允许共享使用,则系统不会进入死锁状态,比如:SPOOLing技术

c:该策略的缺点–并不是所有的资源都可以改造成可共享使用资源,为了系统安全性,很多地方还保护这种互斥性

②:破坏不剥夺条件:
不剥夺条件:在进程所获得的资源在未使用完之前,不能由其他进程强行夺走,只能主动释放

方案一:
当某个进程请求新的资源得不到满足的时候,它必须释放保持的所有资源,待以后需要时再重新申请。也就是说,即使某些资源没有使用完毕,也需要主动释放,从而破坏了不可剥夺的条件

方案二:
当某个进程需要的资源被其他进程占有的时候,可以由操作系统协助,将想要的资源强行剥夺。这种一般是需要考虑各进程的优先级

该策略的缺点

a:实现起来比较复杂

b:释放以获得的资源可能造成前一段工作的失效,因此这种方法一般只适用于易保存和恢复的资源。比如CPU

c:反复的请求和释放资源会增加系统的开销,降低系统的吞吐量

d:如果采用方案一,如果请求不到新的资源就需要重新释放手里的所有资源,以后再重新申请,如果一直都请求不到,就会发生饥饿的情况

③:破坏请求和保持条件
请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又被其他进程所占有,此时请求进程被阻塞,但又对自己的保持的资源不放

采用静态分配方法,即一个进程开始运行前就申请完自己所有需要的资源,在未获得所有资源之前,不让其投入运行,一旦运行,这些资源就一直归他所有,该进程就不会再去申请其他资源

缺点:
有些资源可能只需要用很短的时间,因此如果进程在整个运行期间都保持拥有所有资源的话,就会造成资源的浪费,降低资源利用率。另外该策略可能造成某些进程饥饿

④:破坏等待条件
等待链:存在一种进程资源的循环等待链,链中每一个进程以获得的资源同时被下一个进程所请求

可采用顺序资源分配法:
首先给系统中的资源编号,规定每个进程只能按照标号递增的顺序请求资源,同类的资源(即编号相同的资源)一次申请完。

原理分析:
一个进程只有占有小编号的资源的时候,才有资格申请更大编号的资源。按此规则,以持有大编号资源的进程不可能回过头申请小编号的资源,从而不会产生循环等待的现象

该策略的缺点:

a:不方便增加新的设备,因为可能需要重新分配编号

b:进程实际使用的顺序可能与编号递增顺序不一致,会导致资源浪费

c:必须按照次序申请资源,用户编程麻烦

小结:

在这里插入图片描述
2):动态策略–避免死锁
什么是安全序列
所谓安全序列,就是如果系按照某种顺序分配资源,则每一个进程都能顺利完成,只要找出一个安全序列,系统就是安全的。

什么是系统的不安全状态,与死锁有何联系
①如果系统分配资源后,系统找不到任何一个安全序列,系统就进入了不安全状态,这就意味着之后可能所有的进程都无法顺利的执行下去。当然,如果有进程提前归还了资源,那系统可能重新进入到安全状态,不过这开始需要考虑最坏的情况的

②如果系统进入了安全状态,就一定不会发生死锁。如果系统进入了不安全状态,就不一定会发生死锁

如何避免系统进入不安全状态–银行家算法
①而一再资源分配之前预先判断这次分配是否会导致系统进入不安全状态,以此决定是否答应资源分配请求(如果此次的资源分配容易让系统进入不安全状态,就会暂停这次的资源分配请求的响应),这也是“银行家算法”的核心思想

②银行家算法是荷兰学者Dijkstra为银行系统设计的,以确保银行在发放贷款的时候,不会发生不能满足客户需要的情况。后来算法被用在操作系统中,用于避免死锁。

在这里插入图片描述
在这里插入图片描述
这个银行家算法,在于当有进程有资源请求的时候,系统会考虑满足这次资源分配后,剩余的资源,能否满足其他进程所需的最大需求。如果满足就响应这次的资源需求请求,如果不满足就暂时不响应,如此让系统始终处于安全序列中。

银行家算法步骤
①检查此次申请是否超过了之前声明的最大的需求数

②检查此时系统剩余的可用资源啊是否还能满足这次请求

③试着分配,更改数据结构

④用安全性算法检查此次分配是否会导致系统进入不安全的状态

数据结构:
①长度为m的一维数组Available表示还有多少可用资源

②n*m矩阵max表示各进程对资源的各自的最大需求数

③n*m矩阵Allocation表示已给进程分配了多少资源

④Max-Allocation=Need表示各进程最多还需要多少资源

⑤用长度为m的一维数组Request表示进程此次申请的各种资源数

在这里插入图片描述
假设系统中有n个进程,m个资源
每个进程在运行前先声明对各种资源的最大需求数,则可用一个nm的矩阵(可用二维数组实现)表示所有进程对各种资源的最大需求数。不妨称为最大需要矩阵Max,Max[i,j]=k表示进程Pi最多需要K个资源Rj。同理,系统可以用一个nm的分配矩阵Allocation表示对所有进程的资源分配情况。Max-Allocation=Need矩阵,表示各进程最多还需要多少各类资源
另外还可以用一个长度为m的一维数组Available表示当前系统还有多少可用资源
某进程Pi向系统申请资源,可用一个长度为·m的一维数组Request表示本次申请的各种资源量

允许死锁发生的方式下,操作系统可以进行死锁的检测和解除两种方式

1)死锁的检测
用某种数据结构来保存资源的请求和分配信息,提供一种算法,利用请求和分配信息来检测进程是否进入了死锁状态

这里用得资源分配图来存储资源的分配情况

资源分配图有两种节点
①进程节点:对应一个节点

②资源节点:对应一类资源,一类资源可能有多个

有两种边
进程节点到资源节点的边:表示进程想要申请几个资源(每条边代表一个)

资源节点到进程节点的边:表示已经为进程分配了几个资源(每条边代表一个)

在这里插入图片描述
如果系统中剩余的资源满足进程最大的资源需求数,那么这个进程就可以顺利的执行下去,不会发生阻塞。
如果这个进程执行完毕了,就会把资源归还给系统,那么系统就会把其余正在等待·该资源的进程激活,并使其顺利的执行下去
如果按上述流程进行分析,最终能消除所有的边,这样的图就被称为“可完全简化”,此时一定没有死锁的发生(相当于能找到一个安全序列)
如果不能消除所有的边,那么就是发生了死锁

2)死锁的解除:
死锁的解除有三种形式

①资源剥夺法
挂起(暂时放到外存上)某些死锁进程,并抢夺它的资源。将这些资源分配给其他的死锁进程。但是应防止挂起的进程长时间得不到资源而饥饿

②撤销进程法
强制撤销部分,全部的死锁进程,并剥夺这些进程的资源。这种方式实现简单,但是付出的代价很大

③进程回退法:
让一个或多个死锁进程回退到足以避免死锁的地步,这就要求系统要记录进程的历史信息,设置还原点

根据什么对进程进行处理:
①:进程优先级比较低的进程

②:已执行多长时间,执行时间越短的进程越可能被处理

③:该进程还有多长时间执行完毕,越长的进程越可能被处理

④:进程已经使用了多少资源,使用资源越多的进程越可能被要求做出牺牲

⑤:进程时交互式的,还是批处理的,批处理的因为更多是数据的处理,并不直接与用户交互。所以优先对此进行开刀

如果系统中不采取预防死锁的措施,也不采取避免死锁的措施,系统就很可能会发生死锁

小结:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值