目录
1.进程的概念和定义
2.进程的特征
3.进程的状态
4.进程状态转换
5.进程的构成
5.1进程控制块(PCB)
5.1.1PCB的组织方式
5.2程序段
5.3数据段
6.如何控制进程
6.1进程的创建
6.2进程的终止
6.3进程的阻塞和唤醒
7.进程之间的通信手段
7.1共享内存
7.2消息传递
7.2.1直接通信
7.2.3间接通信
7.3管道通信
进程是计算机系统中正在运行的程序的实例。它是操作系统对程序执行的基本单位,可以看作是程序在执行过程中的动态表现。每个进程都有自己的内存空间、代码、数据和执行状态。多个进程可以同时运行在计算机系统中。
从不同的角度,进程可以有不同的定义,比较典型的定义有:
引入进程实体的概念后,我们可以把传统操作系统中的进程定义为:“进程是进程实体的运行过程,是系统进行资源配和调度的一个独立单位。”
进程的基本特征是对比单个程序的顺序执行提出的,也是对进程管理提出的基本要求。
进程有以下特征:
1)动态性。进程是程序的一次执行,它有着创建、活动、暂停、终止等过程,具有一定的生命周期,是动态地产生、变化和消亡的。动态性是进程最基本的特征。
2)并发性。指多个进程实体同存于内存中,能在一段时间内同时运行。引入进程的目的就是使进程能和其他进程并发执行。并发性是进程的重要特征,也是操作系统的重要特征
3)独立性。指进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单位。凡未建立PCB的程序,都不能作为一个独立的单位参与运行。
4)异步性。由于进程的相互制约,使得进程按各自独立的、不可预知的速度向前推进。异步性会导致执行结果的不可再现性,为此在操作系统中必须配置相应的进程同步机制。
进程在其生命周期内,由于系统中各进程之间的相互制约及系统的运行环境的变化,使得进程的状态也在不断地发生变化。通常进程有以下5种状态,前3 种是进程的基本状态。
1)运行态。进程正在处理机上运行。在单处理机中,每个时刻只有一个进程处于运行态。
2)就绪态。进程获得了除处理机外的一切所需资源,一旦得到处理机,便可立即运行。系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。
3)阻塞态,又称等待态。进程正在等待某一事件而暂停运行,如等待某资源为可用(不包括处理机)或等待输入/输出完成。即使处理机空闲,该进程也不能运行。系统通常将处于阻塞态的进程也排成一个队列,甚至根据阻塞原因的不同,设置多个阻塞队列。
4)创建态。进程正在被创建,尚未转到就绪态。创建进程需要多个步骤:首先申请一个空白PCB,并向PCB中填写用于控制和管理进程的信息,然后为该进程分配运行时所必须的资源:最后把该进程转入就绪态并插入就绪队列。但是,如果进程所需的资源尚不能得到满足,如内存不足,则创建工作尚未完成,进程此时所处的状态称为创建态。
5)结束态。进程正从系统中消失,可能是进程正常结束或其他原因退出运行。进程需要结束运行时,系统首先将该进程置为结束态,然后进一步处理资源释放和回收等工作。
进程五态模型:
需要注意的是,一个进程从运行态变成阻塞态是主动的行为,而从阻塞态变成就绪态是被动的行为,需要其他相关进程的协助。
进程创建时,操作系统为它新建一个PCB,该结构之后常驻内存,任意时刻都可以存取,并在进程结束时删除。PCB是进程实体的一部分,是进程存在的唯一标志。
进程执行时,系统通过其 PCB 了解进程的现行状态信息,以便操作系统对其进行控制和管理;进程结束时,系统收回其PCB,该进程随之消亡。
当操作系统欲调度某进程运行时,要从该进程的 PCB 中查出其现行状态及优先级;在调度到某进程后,要根据其PCB 中所保存的处理机状态信息,设置该进程恢复运行的现场,并根据其PCB中的程序和数据的内存始址,找到其程序和数据:进程在运行过程中,当需要和与之合作的进程实现同步、通信或访问文件时,也需要访问 PCB;当进程由于某种原因而暂停运行时,又需将其断点的处理机环境保存在PCB中。可见,在进程的整个生命期中,系统总是通过PCB对进程进行控制的,亦即系统唯有通过进程的PCB才能感知到该进程的存在。
在一个系统中,通常存在着许多进程的PCB,有的处于就绪态,有的处于阻塞态,而且阻塞的原因各不相同。为了方便进程的调度和管理,需要将各进程的PCB用适当的方法组织起来。目前,常用的组织方式有链接方式和索引方式两种。链接方式将同一状态的PCB 链接成一个队列,不同状态对应不同的队列,也可把处于阻塞态的进程的 PCB,根据其阻塞原因的不同,排成多个阻塞队列。索引方式将同一状态的进程组织在一个索引表中,索引表的表项指向相应的 PCB,不同状态对应不同的索引表,如就绪索引表和阻塞索引表等
程序段就是能被进程调度程序调度到CPU执行的程序代码段。
一个进程的数据段,可以是进程对应程序加工处理的原始数据,也可以是程序执行时候产生的中间或最终结果。
进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。在操作系统中,一般把进程控制用的程序段称为原语,原语的特点是执行期间不允许中断,它是一个不可分割的基本单位。
允许一个进程创建另一个进程,此时创建者称为父进程,被创建的进程称为子进程。子进程可以继承父进程所拥有的资源。当子进程被撤销时,应将其从父进程那里获得的资源归还给父进程。此外,在撤销父进程时,通常也会同时撤销其所有的子进程。
在操作系统中,终端用户登录系统、作业调度、系统提供服务、用户程序的应用请求等都会引起进程的创建。操作系统创建一个新进程的过程如下(创建原语):
引起进程终止的事件主要有:
操作系统终止进程的过程如下(终止原语):
1)根据被终止进程的标识符,检索出该进程的 PCB,从中读出该进程的状态。
2)若被终止进程处于执行状态,立即终止该进程的执行,将处理机资源分配给其他进程
3)若该进程还有子孙进程,则应将其所有子孙进程终止。
4)将该进程所拥有的全部资源,或归还给其父进程,或归还给作系统
5)将该PCB从所在队列(链表)中删除。
正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成新数据尚未到达或无新任务可做等,进程便通过调用阻塞原语(Block),使自己由运行态变为阻塞态。可见,阻塞是进程自身的一种主动行为,也因此只有处于运行态的进程(获得 CPU),才可能将其转为阻塞态。阻塞原语的执行过程如下:
1)找到将要被阻塞进程的标识号对应的PCB。
2)若该进程为运行态,则保护其现场,将其状态转为阻塞态,停止运行。
3)把该PCB插入相应事件的等待队列,将处理机资源调度给其他就绪进程
当被阻塞进程所期待的事件出现时,如它所启动的IO操作已完成或其所期待的数据已到达,由有关进程(比如,释放该 IO 设备的进程,或提供数据的进程)调用唤醒原语 (Wakeup),将等待该事件的进程唤醒。唤醒原语的执行过程如下:
1)在该事件的阻塞队列中找到相应进程的PCB
2)将其从阻塞队列中移出,并置其状态为就绪态
3)把该PCB插入就绪队列,等待调度程序调度。
应当注意,Block 原语和 Wakeup 原语是一对作用刚好相反的原语,必须成对使用。如果在某进程中调用了 Block 原语,则必须在与之合作的或其他相关的进程中安排一条相应的 Wakeup原语,以便唤醒阻塞进程;否则,阻塞进程将会因不能被唤醒而永久地处于阻塞状态。
在通信的进程之间存在一块可直接访问的共享空间,通过对这片共享空间进行写/读操作实现进程之间的信息交换。
注意,进程空间一般都是独立的,进程运行期间一般不能访问其他进程的空间,想让两个进程共享空间,必须通过特殊的系统调用实现,而进程内的线程是自然共享进程空间的。简单理解就是,甲和乙中间有一个大布袋,甲和乙交换物品是通过大布袋进行的,甲把物品放在大布袋里,乙拿走。但乙不能直接到甲的手中拿东西,甲也不能直接到乙的手中拿东西。
在消息传递系统中,进程间的数据交换以格式化的消息(Message) 为单位。若通信的进程之间不存在可直接访问的共享空间,则必须利用操作系统提供的消息传递方法实现进程通信。进程通过系统提供的发送消息和接收消息两个原语进行数据交换。
直接通信方式。发送进程直接把消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上,接收进程从消息缓冲队列中取得消息
需要通信的每个进程必须明确指定通信的接收者或发送者。采用这种方案,原语send()和receive()定义如下:
- send(P, message):向进程P发送message。
- receive(Q, message):从进程Q接收message。
这种方案的通信链路具有以下属性:
- 在需要通信的每对进程之间,自动建立链路。进程仅需知道对方身份就可进行交流。
- 每个链路只与两个进程相关。
- 每对进程之间只有一个链路。
这种方案展示了寻址的对称性(symmetry),即发送和接收进程必须指定对方,以便通信。这种方案的一个变形采用寻址的非对称性(asymmetry),即只要发送者指定接收者,而接收者不需要指定发送者。采用这种方案,原语send()和receive()的定义如下:
- send(P, message):向进程P发送message。
- receive(id, message):从任何进程,接收message,这里变量id被设置成与其通信进程的名称。
间接通信方式。发送进程把消息发送到某个中间实体,接收进程从中间实体取得消息。这种中间实体一般称为信箱。该通信方式广泛应用于计算机网络中。
通过邮箱或端口来发送和接收消息。邮箱可以抽象成一个对象,进程可以向其中存放消息,也可从中删除消息.每个邮箱都有一个唯一的标识符。例如,POSIX消息队列采用一个整数值来标识一个邮箱。一个进程可以通多个不同邮箱与另一个进程通信,但是两个进程只有拥有一个共享邮箱时才能通信。原语send()和receive()定义如下:
- send(A, message):向邮箱A发送message。
- receive(A, message):从邮箱A接收message。
对于这种方案,通信链路具有如下特点:
- 只有在两个进程共享一个邮箱时,才能建立通信链路。
- 一个链路可以与两个或更多进程相关联。
- 两个通信进程之间可有多个不同链路,每个链路对应于一个邮箱。
现在假设进程P1、P2和P3都共享邮箱A。进程P1发送一个消息到A,而进程P2和P3都对A执行receive()。哪个进程会收到P1发送的消息?答案取决于所选择的方案:
- 允许一个链路最多只能与两个进程关联。
- 允许一次最多一个进程执行操作receive()
- 允许系统随意选择一个进程以便接收消息(即进程P2和P3两者之一都可以接收消息,但不能两个都可以)。系统同样可以定义一个算法来选择哪个进程是接收者(如轮转(round robin),进程轮流接收消息)。系统可以让发送者指定接收者。
管道通信是消息传递的一种特殊方式。所谓“管道”,是指用于连接一个读进程和一个写进程以实现它们之间的通信的一个共享文件,又名pipe文件。向管道(共享文件)提供输入的发送进程(即写进程),以字符流形式将大量的数据送入(写)管道,而接收管道输出的接收进程(即读进程)则从管道中接收(读)数据。为了协调双方的通信,管道机制必须提供以下三方面的协调能力:互斥、同步和确定对方的存在。
在Linux中,管道是一种使用非常频繁的通信机制。从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现如下:
1)限制管道的大小。实际上,管道是一个固定大小的缓冲区。在 Linx 中,该缓冲区的大小为 4KB,这使得它的大小不像文件那样不加检验地增长。使用单个固定缓冲区也会带来问题,比如在写管道时可能变满,这种情况发生时,随后对管道的 write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用写
2)读进程也可能工作得比写进程快。当所有当前进程数据已被读取时,管道变空。当这种情况发生时,一个随后的read0调用将默认地被阻塞,等待某些数据被写入,这解决了read0调用返回文件结束的问题。
注意:从管道读数据是一次性操作,数据一旦被读取,就释放空间以便写更多数据。管道只能采用半双工通信,即某一时刻只能单向传输。要实现父子进程互动通信,需定义两个管道。