操作系统 第二章:进程管理

目录

一:进程与线程

进程的概念和特征

进程的状态与转换

进程控制

进程的通信

线程概念和多线程模型

二:处理机调度

处理机调度概念、层次

调度的时机、切换与过程

调度算法的评价指标

调度算法

三:进程同步

进程同步、互斥

进程互斥软件实现方法

进程互斥硬件实现方法

信号量机制

生产者—消费者问题

吸烟者问题

读者写者问题

哲学家进餐问题

管程

四:死锁

死锁的概念

预防死锁

避免死锁

死锁的检测和解除


一:进程与线程

  • 进程的概念和特征

引入多道程序技术之后,为了方便操作系统管理,完成个程序并发执行,引入了进程、进程实体的概念。

系统为每个运行的程序配置一个数据结构,称为进程控制块(PCB),用来描述进程的各种信息

程序段、数据段、PCB三部分组成了进程实体。创建进程就是创建PCB,撤销进程就是撤销PCBPCB是进程存在的唯一标志。

进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位

进程是动态的、进程实体是静态的。

程序段:存放要执行的代码。

数据段:存放程序运行过程中处理的各种数据。

PCB:{进程描述信息[进程标识符PID、用户标识符UID]、

进程控制和管理信息[进程当前状态、进程优先级]、

资源分配清单[程序段指针、数据段指针、键盘、鼠标]、

处理剂相关信息[各种寄存器值]}

进程的组织方式:链接方式[按照进程状态将PCB分为多个序列、操作系统持有指向各个队列的指针]、索引方式[根据进程状态的不同,建立几张索引表、操作系统持有指向各个索引表的指针]

进程的特征:

动态性(最基本的特征):进程是程序的一次执行过程,是动态地产生、变化和消亡的;

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

独立性:进程是能独立运行、独立获取资源、独立接受调度的基本单位;

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

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

  • 进程的状态与转换

进程的三种基本状态:

运行态:占有CPU,并运行;

就绪态:已经具备运行条件,但由于没有空闲CPU,而暂时不能运行;

阻塞态:因等待某一事件而暂时不能运行。

另外两种状态:创建态(新建态)、终止态(结束态)。

进程状态间的转换:

就绪-->运行:进程被调度

运行-->就绪:时间片道,或CPU被其他高优先级的进程抢占

运行-->阻塞:等待系统资源分配,或等待某事件发生(主动行为)

阻塞-->就绪:资源分配到位,等待的事件发生(被动行为)

创建-->就绪:系统完成创建进程相关的工作

运行-->终止:进程运行结束,或运行过程中遇到不可修复的错误

  • 进程控制

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

用原语实现进程控制。原语的特点是执行期间不允许中断,只能一气呵成。不可被中断的操作即原子操作。“关中断指令”“开中断指令”

进程状态转换相关原语,无非做三类事情:

  1. 更新PCB中的信息(如修改进程状态标志、将运行环境保存到PCB、从PCB恢复运行环境)[所有的进程控制原语一定都会修改进程状态标志;剥夺当前运行进程的CPU使用权必然需要保存其运行环境;某进程开始运行前必然要恢复其运行环境]
  2. 将PCB插入合适的队列
  3. 分配回收资源

进程的创建:

创建原语(申请空白PCB、为新进程分配所需资源、初始化PCB、将PCB插入就绪队列)

引起进程创建的事件(用户登录、作业调度、提供服务、应用请求)

进程的终止:

撤销原语(从PCB集合中找到终止进程的PCB、若进程正在运行,立即剥夺CPU,将CPU分配给其他进程、终止其所有进程、将该进程拥有的所有资源归还给父进程或操作系统、删除PCB)

引起进程终止的事件(正常结束、异常结束、外界干预)

进程的阻塞和唤醒:

进程的阻塞(阻塞原语[找到要阻塞的进程对应的PCB、保护进程运行现场,将PCB状态信息设置为“阻塞态”,暂时停止进程运行、将PCB插入相应事件的等待队列]、引起进程阻塞的事件[需要等待系统分配某种资源、需要等待相互合作的其他进程完成工作])

进程的唤醒(唤醒原语[在事件等待队列中找到PCB、将PCB从等待队列移除,设置进程为就绪态、将PCB插入就绪队列,等待被调度]、引起进程唤醒的事件[等待事件发生])

进程的切换:

切换原语(将运行环境信息存入PCB、PCB移入相应队列、选择另一个进程执行,并更新其PCB、根据PCB恢复新进程所需的运行环境)

引起进程切换的事件(当前进程时间片到、有更高优先级的进程到达、当前进程主动阻塞、当前进程终止)

  • 进程的通信

共享存储

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

基于存储区的共享:在内存中画出一块共享存储区,数据的形式、存放位置都由进程控制,而不是操作系统。相比之下,这种共享方式速度更快,是一种高级通信方式

管道通信:用于连接读写进程的一个共享文件。其实就是在内存中开辟一个大小固定的缓冲区

管道只能采用半双工通信,某一时间段内只能实现单向传输,如果要实现双向同时通信,则需要设置两个管道;

各进程要互斥地访问管道;

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

如果没写满,就不允许读。如果没读空,就不允许写;

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

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

直接通信方式:直接挂到接收进程的消息缓冲队列上;

间接通信方式:消息先发到中间体(信箱)

  • 线程概念和多线程模型

引入线程后,进程只作为除CPU外的系统资源的分配单元。

线程属性

是处理机调度的单位;

多CPU计算机中,多个线程可占用不同的CPU;

每个线程都有一个线程ID、线程控制块TCB;

线程也有就绪、阻塞、运行三种基本状态;

线程几乎不拥有系统资源;同一进程的不同线程间共享进程的资源;

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

同一进程中的线程切换,不会引起进程切换;

不同进程中的线程切换,会引起进程切换;

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

切换进程,系统开销较大。

线程的实现方式

用户级线程:线程切换在用户态即可完成。对用户不透明,对操作系统透明。

内核级线程:由操作系统内核完成。内核级线程的切换必然需要在核心态下才能完成。对用户透明。

在同时支持用户级线程和内核级线程的系统中,可采用二者组合的方式,将n个用户级线程映射到m个内核级线程上。(n>=m)

多对一模型:多个用户及线程映射到一个内核级线程。每个用户进程只对应一个内核级进程。 优点:用户级线程的切换在用户空间即可完成,线程管理的系统开销小,效率高。  缺点:当一个用户级进程被阻塞,整个进程就会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。

一对一模型:一个用户及线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。  优点:当一个线程被阻塞,别的线程还可以继续进行,并发能力强。多线程可在多处理机上并行执行。  缺点:一个用户进程会占用多个内核级线程,线程切换由系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。

多对多模型:n用户级线程映射到m个内核级线程。克服了多对一模型并发度不高的缺点,又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。

二:处理机调度

  • 处理机调度概念、层次

高级调度(作业调度):辅存(外存)与内存之间的调度。每个作业只调度一次,调出一次。作业调入时会建立相应的PCB,作业调出时撤销PCB。

中级调度:将暂时不能运行的进程调至外存等待。等它具备了运行条件且内存又空闲,重新调入。调出时PCB会留在内存。暂时调到外存等待的进程状态为挂起状态。被挂起进程的PCB会被放到挂起队列中。

进程的挂起态与七状态模型

低级调度(进程调度):主要任务是按照某种方法和策略从就绪队列中选取一个进程,将处理机分配给它。最基本的调度。

  • 调度的时机、切换与过程

需要进行进程调度:当前运行的进程主动或被动放弃处理机。

不能进行进程调度的情况:处理中断;进程在操作系统内核程序临界区中;原子操作过程中。

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

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

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

非剥夺调度方式(非抢占方式):只允许进程主动放弃处理机。系统开销小但是无法及时处理紧急任务,适合于早期的批处理系统。

剥夺调度方式(抢占方式):适合于分时操作系统、实时操作系统。

“狭义的进程调度”指的是从就绪队列中选中一个要运行的进程。

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

广义的进程调度包含了选择一个进程和进程切换两个步骤。

进程切换的过程主要完成:对原来运行进程各种数据的保存;对新的进程各种数据的恢复。

  • 调度算法的评价指标

CPU利用率:指CPU“忙碌”时间占总时间的比例。

系统吞吐量:单位时间内完成作业的数量。

周转时间:从作业被提交给系统开始,到作业完成为止的时间间隔。(作业在外存后备队列上等待作业调度的时间+进程在就绪队列上等待的时间+进程在CPU上执行的时间+进程等待I/O操作完成的时间)

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

带权周转时间:作业周转时间/作业实际运行时间。

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

等待时间:指进程、作业处于等待处理机状态时间之和,等待时间越长,用户满意度越低。

对于进程:等待时间就是指进程建立后等待被服务时间之和,在等待I/O完成的期间其实进程也是在被服务的,不计入等待时间。

对于作业:不仅要考虑建立进程后的等待时间,还要加上作业在外存后备队列中等待的时间。

响应时间:从用户提交请求到首次产生响应所用的时间。

  • 调度算法

下面三种都用于作业调度和进程调度

先来先服务FCFS:非抢占式,不会导致饥饿 (优点:公平、算法实现简单。 缺点:排在长作业(进程)后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好。)

短作业优先SJF:有抢占式(SRTN最短剩余时间优先算法)和非抢占式,在所有进程几乎同时到达/同时可运行时,采用SJF调度算法的平均等待时间、平均周转时间最少,如果不断有短作业到来,长作业会“饥饿” (优点:“最短的”平均等待时间、平均周转时间  缺点:不公平。对短作业有利,长作业不利。另外,作业/进程运行时间是由用户提供的,并不一定真实,不一定能做到短作业优先)

高响应比优先HRRN:综合考虑作业/进程的等待时间和要求服务时间。响应比=(等待时间+要求服务时间)/要求服务时间。非抢占式。不会导致饥饿  (优缺点:综合考虑了等待时间和运行时间(要求服务时间),等待时间相同时,要求服务时间短的优先,服务时间相同,先来的优先)

算法

抢占?

优点

缺点

考虑等待时间&运行时间?

饥饿

FCFS

公平、实现简单

对短作业不利

等待时间

不会

SJF/SPF

都有

“最短”平均等待/周转时间

对长作业不利

运行时间

HRRN

上述的权衡折中

等待+运行时间

不会

时间片轮转(RR:公平、轮流地为各个进程服务。按到达顺序让进程都执行一个时间片,用完重新排队。用于进程调度。抢占式。不会饥饿。 (优点:公平、响应快,适用于分时操作系统; 缺点:由于高频率的进程切换,因此有一定开销;不区分任务的紧急程度)

优先级调度算法:设置优先级。用于作业和进程调度。抢占式非抢占的都有。会饥饿。 (优点:用优先级区分紧急程度、重要程度,适用于实时操作系统。 缺点:若不断有高优先级进程到来,可能导致饥饿)

多级反馈队列调度算法:对其他算法折中权衡。用于进程调度。抢占式。会饥饿。  思想:设置多级就绪队列,各级队列优先级从高到低,时间片从小到大。新进程到达先进入第1级队列,按FCFS原则等待分配时间片。若用完进程还未结束,则进程进入下一级队列队尾。若已经是最下级,则放入本级队尾。只要当k级队列为空,才会对k+1级队头进程分配时间片  (优缺点:对各类型进程相对公平,每个新到达的都可以很快得到响应,短进程用时少,不必实现估计进程的运行时间,可将因I/O而阻塞的进程重新防回原队列,I/O型进程就可以保持较高优先级)

算法

抢占?

优点

缺点

饥饿

时间片

公平,适用于分时系统

频繁切换有开销,不区分优先级

不会

优先级

都有

区分优先级,适用于实时系统

饥饿

多级

平衡优秀

三:进程同步

  • 进程同步、互斥

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

临界资源:一个时间段内只允许一个进程使用的资源。

对临界资源的互斥访问,可以在逻辑上分为:进入区、临界区、退出区、剩余区四个部分。

互斥访问原则

  1. 空闲让进;
  2. 忙则等待;
  3. 有限等待;
  4. 让权等待。
  • 进程互斥软件实现方法

单标志法:两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程。也就是说每个进程进入临界区的权限只能被另一个进程赋予。主要问题是:违背“空闲让进”原则

双标志先检查法:标记进入临界区的意愿,检查对方想进入就等待,不想则改变标记位,进入。主要问题:违背“忙则等待”原则。因为进入区的检查和上锁不是一气呵成的。

双标志后检查法:先改变自己的标记,再判断对方是否进入。违背了“空闲让进”、“有限等待”

Peterson算法:表示自己有进入的意愿,都愿意让对方先进。只有对方想进,并且最后一次是自己让,自己就循环等待。未遵循让权等待。

  • 进程互斥硬件实现方法

中断屏蔽方法:利用“开关中断指令”实现。 优点:简单、高效。缺点:不适用于多处理剂,只适用于操作系统内核进程,不适用于用户进程。只能运行在内核态。

TestAndSet指令:简称TS指令,或TSL指令。执行过程不允许被中断。查询当前是否上锁,如果上锁,则等待,若否,则上锁并进入(一气呵成)。 优点:实现简单,无需严格检查是否有逻辑漏洞适用于多处理机系统。 缺点:不满足“让权等待”,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,造成忙等。

Swap指令:执行不允许被中断。与TSL类似。 优点:实现简单,无需严格检查是否会有逻辑漏洞,适用于多处理机环境。 缺点:不满足“让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,造成忙等。

  • 信号量机制

整型信号量:用一个整数型变量作为信号量,用来表示系统中某种资源的数量。Wait原语申请资源,检查上锁一气呵成;signal退出区,释放资源。存在问题:不满足“让权等待”。

记录型信号量:wait操作申请资源,当资源数小于零,使用block原语是进程从运行态进入阻塞态,并挂到信号量S的等待队列中。Signal原语释放资源,若有进程等待将该进程从阻塞态变为就绪态。

信号量机制实现进程互斥

  1. 分析并发进程的关键活动,规定临界区;
  2. 设置互斥信息量mutex,初值为1
  3. 在临界区之前执行P(mutex);
  4. 在临界区之后执行V(mutex)。

注:对不同的临界资源需要设置不同的互斥信息量。

信号量机制实现进程同步(保证一前一后执行)

1.分析什么地方需要实现“同步关系”;

2.设置同步信息量S,初始化为0

3.在“前操作”之后执行V(S);(相当于释放操作)

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

信号量机制实现前驱关系

1.要对每对前驱关系各设置一个同步变量;

2.在“前操作”之后对相应的同步变量执行V操作;

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

  • 生产者—消费者问题

PV操作题目分析步骤:

1.关系分析。找出各个进程,分析它们之间的同步、互斥关系;

2.整理思路。确定PV操作大致顺序;

3.设置信号量。并根据题目条件确定信号量初值。

(P操作互斥一般在同步之后进行)

多生产者—多消费者问题。

  • 吸烟者问题

  • 读者写者问题

  • 哲学家进餐问题

  • 管程

为什么要引入管程?

信号量机制:编写困难、易出错。

管程是一种特殊的软件模块,由以下部分组成

1.局部于管程的共享数据结构说明;

2.对该数据结构进行操作的一组过程;

3.对局部于管程的共享数据设置初始值的语句;

4.管程有一个名字。

管程的基本特征

1.局部于管程的数据只能被局部于管程的过程所访问;

2.一个进程只有通过调用管程内的过程才能进入管程访问共享数据;

3.每次只允许一个进程在管程内执行某个内部过程。

补充:各进程必须互斥访问管程的特性是由编译器实现的;可在管程中设置条件变量及等待/唤醒操作以解决同步问题。

四:死锁

  • 死锁的概念

在并发环境下,各进程因竞争资源而造成的一种互相等待双方手里的资源,导致各进程都阻塞,都无法向前推进的现象,就是“死锁”。

饥饿:由于长期得不到想要的资源,某进程无法向前推进的现象。

死循环:某进程执行过程中一直跳不出来某个循环的现象。可能是bug,可能是故意设计。

共同点

区别

死锁

都是进程无法顺利向前推进的现象

死锁一定是“循环等待对方手里的资源”导致的,因此如果有死锁现象,至少有两个或两个以上的进程同时发生死锁。另外,发生死锁的进程一定处于阻塞态。

饥饿

可能只有一个进程发生饥饿。发生饥饿的进程既可能是阻塞态,也可能是就绪态

死循环

可能只有一个进程发生死循环。死循环的进程可以上处理机运行,只不过无法像期待的那样顺利推进。死锁和饥饿是管理者(操作系统)的问题,死循环是被管理者的问题。

死锁产生的必要条件:(4个)

互斥条件:只有对必须互斥使用的资源的争夺才会导致死锁。

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

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

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

什么时候会发生死锁?

1.对系统资源的竞争;

2.进程推进顺序非法;

死锁处理策略:

1.预防死锁;(不允许死锁发生、静态策略)

2.避免死锁;(不允许死锁发生、动态策略)

3.死锁的检测和解除。(允许死锁发生)

  • 预防死锁

破坏互斥条件:把只能互斥使用的资源改造为允许共享使用。SPOOLing技术。缺点:可行性不高,很多时候无法破坏互斥条件。

破坏不剥夺条件:1.申请的资源得不到满足,立即释放拥有的所有资源;2.申请的资源被其他进程占用,由操作系统剥夺。缺点:实现复杂,剥夺资源可能导致部分工作失效,反复申请和释放导致系统开销大,可能导致饥饿。

破坏请求和保持条件:运行前分配好所有需要的资源,之后一直保持。缺点:资源利用率低,可能导致饥饿。

破坏循环等待条件:给资源编号,必须按编号从小到大的顺序申请资源。缺点:不方便增加新设备,会导致资源浪费,用户编程麻烦。

  • 避免死锁

安全序列:系统按照这个序列分配资源,每个进程都能顺利完成。

若找不出安全序列,系统就进入了不安全状态。

银行家算法

  • 死锁的检测和解除

检测:1.用某种数据结构来保存资源的请求和分配信息;2.提供一种算法,利用上述信息来检测系统是否已进入死锁状态。

数据结构

两种结点:进程结点(对应一个进程)、资源结点(对应一类资源,一类资源可能有多个)。

两种边:进程节点à资源结点:(表示进程想申请几个资源(每条边代表一个))、资源结点à进程节点(表示已经为进程分配了几个资源(每条边代表一个))。

如果上述数据结构构成的图是不可完全简化的。此时一定发生死锁

解除:用死锁检测算法化简资源分配图后,还连着边的那些进程就是死锁进程。

解除死锁主要方法:

1.资源剥夺法:挂起某些死锁进程,并抢占它的资源,分配给其他死锁进程,但是防止被挂起进程长时间得不到资源而饥饿。

2.撤销进程法。(终止进程法)强制撤销部分、甚至全部死锁进程,并剥夺这些进程的资源。优点:实现简单。但付出的代价可能会很大。

3.进程回退法。让一个或多个死锁进程回退到足以避免死锁的地步。要求记录进程的历史信息,设置还原点。

如何决定对谁动手?

1.进程优先级;

2.已执行多长时间;

3.还要多久能完成;

4.进程已经使用了多少资源;

5.进程是交互式的还是批处理式的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值