进程的描述和控制
进程
1,进程的定义和特征
进程的定义
进程
:资源分配的基本单位。- 进程由三部分组成:
程序段
,相关的数据段
和PCB
。 进程控制块(Process Control Block, PCB)
:描述进程的基本信息和运行状态。PCB的目的是为了是参与并发执行的每个程序(含数据)都能独立的运行,在操作系统中必须为之配置一个专门的数据结构,这就是进程控制块PCB。
创建进程实质是创建进程实体中的PCB。撤销进程实质是撤销进程的PCB。
进程的特征
首先进程和程序是两个完全不同的概念,不仅是因为进程拥有程序没有的PCB还因为进程具有如下特点:
动态性
:进程由创建而产生,由调度而执行,由撤销而消亡。由此:进程实体是有生命周期的是动态的,而程序则只是一组有序指令的集合是静态的。并发性
:多个进程存在于内存中,可以在一段时间内同时运行。而程序(没有创建PCB)是不能参与并发执行的。独立性
:在传统的OS中,独立性是指进程实体是一个能独立运行的,独立获得资源和独立接受调度的基本单位。凡是未建立PCB的程序都不能作为一个独立的单位参与运行。异步性
,是指进程按异步方式运行,即按各自独立的,不可预知的速度向前运行。这也导致了传统意义的程序参与并发,结果是不再现的。为使进程在并发运行时具有异步性,但仍能保证进程并发执行的结果是可在线的,OS引入了相应的同步机制。
2,进程的基本状态和转换
由于多个进程在并发执行时享有共享的资源,致使它们在运行的过程中呈现中断性的运行规律,所以进程在其生命周期内可能具有多种状态。
进程的三种基本状态
就绪状态
:进程已经处于准备好运行的状态,此刻的进程已经获得了除CPU之外的所有资源
。只要获得CPU便可以立即执行。此时如果有多个同样的就绪态进程,他们会按照相应的策略组成就绪队列
,等待执行。执行状态
:这是指进程已经获得了CPU,正在执行中。在一个时刻,单处理系统只能有一个进程处于执行状态,而多处理机系统中,则有多个进程处于执行状态。阻塞状态
:这是指正在执行的进程由于某些事件(I/O请求,申请缓冲区失败等)暂时无法继续执行的状态,即运行的进程受到了阻塞。出现这种状态将导致进程调度,会把处理机分配给其余就绪的进程,而阻塞的进程将暂停,进入阻塞队列
。阻塞状态的进程想要重新获得处理机继续运行,需要进入就绪队列,进入就绪状态,然后在到执行状态。三态转换示意图
:
图中还有两个状态:创建状态(created)和终止状态(terminated)。
创建状态
:在进程成为就绪状态时,需要做三个工作但满足这三个工作后,才能成为就绪态,进入就绪队列。(1)首先,进程申请一个空白的PCB,(2)然后向PCB中填写用于控制和管理进程的信息,(3)最后为进程分配相应运行所需要的资源。完成这三个工程的工作才是就绪态进入就绪队列,但是如果最后因为所需要的资源没有被分配或者没有分配完,不能进入就绪态此时的状态就叫做创建态。
终止状态
:一个进程的时间片用完了,不一定它就结束了,可能回到就绪队列重新等待被调度。进程进入终止状态的情况有:(1)进程到达了自然的结束点(2)出现了无法克服的错误(3)被操作系统终结(4)被其他有终止权的进程终结。都会导致进程进入终止状态。进入终止状态的进程将会清零PCB,并将PCB空间还给系统。在这个过程中,操作系统依然会记录一些信息,保存状态码和一些计时统计数据,供其他进程收集。其他进程提取了这些信息后,操作系统才见进程删除,即清零PCB。
注意
:(1)只有就绪态和运行态可以相互转换,其它的都是单向转换
。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
(2)阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态
。
3,进程调度相关任务,机制和方式
进程调度的任务
主要任务有三个:
- 保存处理机的现场信息。
- 按某种算法选取进程。
- 把处理器分配给进程。
进程调度机制
- 排队器:系统事先将所有就绪进程按照一定的策略排成一个或多个队列,以便进程调度程序能够快速的找到它。
- 分派器:分派器依据进程调度程序所选定的进程,将其从就绪队列中取出,然后进行从分派器到新选出的进程间的上下文切换,将处理机重新分配给所选出的进程。
- 上下文切换器:在对处理机进行分配时,会出现两对上下文的切换。第一对是OS保存当前进程的上下文,第二对是移出分配程序的上下文。
4,进程调度算法
处理机调度
在介绍进程调度算法前,先介绍处理机调度。
在多道系统中,调度的意思就是资源的分配。而处理机也是资源,因此也存在着调度。
在多道程序的环境下,内存中存在着多个进程,数目往往多于处理机,因此对于如何动态的将处理机分配给处于就绪队列的进程就需要一定的算法来实现。分配处理机的任务是由处理机调度程序完成的。
处理机的调度层次
高级调度(又称长程调度或作业调度)
:它的调度对象是作业
。其主要功能就是:根据调度算法将外存后备队列的作业调度进入内存。为他们创建进程和分配资源,并将他们放入就绪队列。在多道批处理中才有高级调度,而实时系统和分时系统中没有。
作业和进程的区别和联系:
作业是一个比程序更加广泛的概念,包含了程序,数据和一份作业说明书。(作业说明书的作用:系统根据这个来对程序进行控制)
一个作业中含有多个进程。这多个进程共同完成一个任务,被称之为作业。
用户提交作业后,系统将对作业进行调度,并未作业创建相应的进程和子进程。
进程是一个程序在一个数据集上的一次执行,而作业是用户提交给系统的一个任务。
作业有作业控制块(Job Control Block JCB),其中保存了系统对作业进行管理和调度所需要的信息。进程有进程控制块(PCB)。
中级调度(又称内存调度)
:调度对象是进程,它的作用主要是将暂时不能运行的进程,调至外存等待。这样做的目的是提高内存利用率和系统吞吐量。当内存有空闲,中级调度将这些进程重新调入内存,修改状态为就绪态。低级调度(又称进程调度或者短程调度)
:调度对象是进程(或内核级线程)。主要作用是根据调度算法决定就绪队列中的那个进程拥有处理机。这是基础调度,因此多道批处理,分时和实时系统都需要这种调度。
批处理系统的调度算法
批处理系统没有太多的用户操作,在该系统中,调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)。
(1)先来先服务 first-come first-serverd(FCFS)
- 最简单的调度算法,非抢占式调度算法。
- 既可以运用于作业调度也可以运用于进程调度。
- 系统依据作业到达的先后顺序来进行调度。在外存的后备队列中根据到达的先后顺序,从其中选择几个先到达作业进入内存,为他们分配资源,创建进程,让其进入就绪队列。当进程使用这种算法时,思想一样,更早进入就绪队列的进程先获得处理机进入运行状态。
- 有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。
(2)短作业优先 shortest job first(SJF)
- 非抢占式的调度算法,按估计运行时间最短的顺序进行调度。
- 可以用于作业调度和进程调度。
- 必须预先估计可能运行时间
- 对长作业不利,长作业可能饿死。有可能一直短作业到来,导致长作业无法执行。
- 人机无法交互
- 未考虑作业紧迫度。
(3)最短剩余时间优先 shortest remaining time next(SRTN)
最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
(4)优先级调度算法 priority-scheduling algorithm(PSA)
- 作为作业调度和进程调度
- 由外部赋予作业优先级,然后根据优先级进行调度,优先级高的想满足调度。
- 在作业调度中,系统从外存的后备队列中根据优先级的高低选择作业调入内存中,分配资源并创建进程。
(5)高响应比优先调度算法 Highest Response Ratio Next(HRRN)
- 既考虑作业的等待时间也考虑作业的运行时间
- 引入动态优先级
交互式系统调度算法
交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。
(1)时间片轮转
将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。
时间片轮转算法的效率和时间片的大小有很大关系:
- 因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。
- 而如果时间片过长,那么实时性就不能得到保证。
(2)优先级调度
为每个进程分配一个优先级,按优先级进行调度。
为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。
该调度算法分为了两种形式:
- 非抢占式优先级调度算法:把处理机分配给就绪队列中的优先级最高的进程后,该进程一直执行下去,直到完成。
- 抢占式优先级调度算法:将处理机分配给就绪队列中优先级最高的进程,如果在执行的过程中出现了优先级更高的进程就将处理机分配给新出现的优先级更高的。
优先级在这个运行期间可以一直不变也可以动态的变化。因此存在两种优先级类型:
- 静态优先级:创建进程时,进程的优先级就被确定为0-255中的某一个整数,并在整个过程中保持不变。
- 动态优先级:创建进程时,先赋予一个优先级,然后在根据进程的推进动态的改变。
(3)多队列调度算法
该算法将一个就绪队列拆分为若干个,将不同类型或者性质的进程固定分配在不同的就绪队列,不同的就绪队列采用不同的调度算法。
(4)多级反馈队列调度算法
执行机制:
(1)设置多个不同优先级的就绪队列。
(2)每个队列的进程采用FCFS算法。当新进程进入内存,首先将它放入第一队列的末尾,按FCFS算法等待调度,当轮到该进程时,如果在一个时间片里面能执行完,就撤离系统,否则将被插入到第二队列末尾等待调度。
(3)按照队列的优先级调度。调度程序首先执行优先级高的。就绪队列中的进程执行完了才执行下一个队列的。
一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次。
多级队列是为这种需要连续执行多个时间片的进程考虑,它设置了多个队列,每个队列时间片大小都不同,例如 1,2,4,8,…。进程在第一个队列没执行完,就会被移到下一个队列。这种方式下,之前的进程只需要交换 7 次。
每个队列优先权也不同,最上面的优先权最高。因此只有上一个队列没有进程在排队,才能调度当前队列上的进程。
可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合。
实时系统
实时调度
实时系统要求一个请求在一个确定时间内得到响应。
分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。
4,进程同步
进程同步机制的主要任务,是对多个相关进程在执行次序上进行协调,使并发执行的诸进程之间能按照一定的规则(或时序)共享系统资源,并能相互的合作,从而使程序的执行具有可再现性。
临界资源,临界区
临界资源
临界资源存在着软件临界资源,硬件临界资源。硬件临界资源如:打印机,磁带机等都是。诸进程对于这些资源的访问采用互斥访问。
临界区
对临界资源进行访问的那段代码
就是临界区
。
为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
// entry section 进入临界区
// critical section;临界区
// exit section退出临界区
//剩余区(除了上述三个区以外的代码都叫做剩余区)
同步与互斥
- 同步:多个进程因为合作产生的直接制约关系,使得进程有一定的先后执行关系。
- 互斥:多个进程在同一时刻只有一个进程能进入临界区。
同步机制遵循的规则
- (1)
空闲让进
:当无进程处于临界区时,表明临界区处于空闲状态,此时可以让一个请求进入临界区的进程立即进入自己的临界区。 - (2)
忙则等待
:当已有进程进入临界区时,表明临界资源正在被访问,此时申请进入的进程必须等待。 - (3)
有限等待
:对要求访问临界区资源的进程,应保证在有限时间内进入自己的临界区,以避免“死等”状况。 - (4)
让权等待
:当进程不能进入自己的临界区时,应立即释放处理机,以避免进程陷入“忙等”的状态。
信号量机制
信号量类型
- (1)整型信号量:整型信号量被定义为一个用于表示资源数目的整型量S,它只能由上述提到的两个原子操作down和up操作访问。
- (2)记录型信号量:除了记录资源的信号量,还含有记录型的数据结构。
- (3)AND型信号量:当进程一次运行需要多个资源,设置多个互斥信号量。这种同步机制下,进程在运行时,一次性分配所有的资源,如果有一个资源可能没有分配到,就会不分配任何资源。
信号量的操作
down(wait,P)
: 如果信号量大于 0 ,执行 -1 操作;如果信号量等于 0,进程睡眠,等待信号量大于 0;up (signal,V)
:对信号量执行 +1 操作,唤醒睡眠的进程让其完成 down 操作。
down 和 up 操作需要被设计成原语,不可分割,通常的做法是在执行这些操作的时候屏蔽中断。
注: p操作也叫做wait操作,sleep操作或者down操作,而v操作也被叫做signal操作,wake-up以及up操作。所以才会看到很多博客和书里面一会p,v,一会down,up。
信号量的应用
利用信号量实现互斥:为了多个进程能互斥的访问临界资源。需要为资源设置一个互斥信号量:mutex,并将其初始值设置为1。在每个进程访问该资源的临界区的时候,需要对mutex进行down操作,这样就能保证互斥的访问。在使用完资源后,进行up操作,释放资源。
typedef int semaphore;
semaphore mutex = 1;
void P1() {
down(&mutex);
// 临界区
up(&mutex)