多道程序环境
下允许多个程序并发执行
,此时这些程序会失去封闭性
,并具有间断性
以及不可再现性
。为此引入了进程(Process)
的概念,以便于更好的去描述和控制程序的并发执行
,实现操作系统
的并发性
和共享性
(操作系统最基本的两个特征)。并发执行
的程序能够独立运行,必须要为之配置一个专门的数据结构,称之为进程控制块(PCB)
。系统利用PCB来描述进程的基本情况和运行状态,进而控制和管理进程。相应的,由程序段
、相应数据段
和PCB
三部分构成了进程映像(进程实体)
。所谓创建进程
实质上是创建进程映像中的PCB
,而撤销进程
实质上是撤销进程的PCB
。!!!进程映像是静态的,进程则是动态的。
!!!PCB是进程存在的唯一标志。
①进程是程序的一次执行过程。
②进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
③进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
进程
是由多道程序
的并发执行
引出的,它和程序是两个不同的概念,进程的基本特征是对比单个程序的顺序执行提出的,也是对进程管理提出的基本要求。进程
是程序的一次执行
,它有着创建
、活动
、暂停
、终止
等过程,具有一定的生命周期,是动态的产生
,变化
和消亡
的。动态性是进程最基本的特征并发性
是指多个进程实体
同时存于内存中,能在一段时间内同时运行
。并发性是进程的重要特征,同时也是操作系统的重要特征,引入进程
的目的就是为了使程序能与其他进程的程序并发直行,从而提高资源利用率
。独立性
是指进程实体
是一个能独立运行
,独立获得资源
和独立接受调度
的基本单位。进程
的相互制约
,使得进程具有执行的间断性
,即进程按各自独立的、不可预知的速度向前推进。异步性
会导致执行结果
的不可再现性
,为此,在操作系统
中必须配置相应的进程同步机制
。PCB
对其进行描述。从结构上看进程实体
是由程序段
、数据段
和进程控制块
三部分组成。一个进程在其生命周期中,由于系统各进程之间的相互制约关系
以及系统的运行环境
的变化,会使得进程的状态也在不断的发生变化(一个进程会经历若干不同的状态),通常情况下会有以下5种状态,前3种是进程的基本状态
。
进程
正在处理机
上运行。在单处理机环境
下,每个时刻最多
只有一个进程
处于运行态
。就绪状态
的进程可能有多个,通常将它们排成一个队列称为就绪队列
。阻塞态
又称等待态
。进程正在等待某一事件而暂停运行,如等待某资源为可用(不包括处理机)或等待输入/输出完成。即使处理机空闲,该进程也不能运行。就绪态
。进程创建
通常需要多个步骤,首先申请一个空白的PCB
,并向PCB中填写一些控制和管理进程的信息
,然后由系统为该进程分配运行时所必需的资源,最后把该进程转入就绪态
。进程正常结束
或者是其他原因中断退出运行
。进程需要结束运行时,系统首先必须置该进程为结束态
,然后再进一步处理资源释放
和回收
等工作。注意区别就绪态和等待态:
就绪态
是指进程
仅仅缺少了处理机
,只要获得处理机资源
就可以立即运行进程
,而等待态
是指进程
需要其他资源(除了处理机)或等待某一件事件。之所以将
处理机
和其他资源
划分开,是因为在分时系统
的时间片轮转机制
中,每个进程分到的时间片是几毫秒,也就是说进程
得到处理机的时间很短,而且非常频繁,进程在运行过程中实际上是频繁的转换到就绪态
,而其他资源(比如说外设)的使用和分配或某一事件的发生(如io操作的完成)对应的时间相对来说很长,进程转换到等待态
的次数也相对较少,这样看来就绪态
和等待态
是进程生命周期
中两个完全不同的状态,需要加以区分。
就绪态
的进程
被调度
后获得处理机资源
(分派处理机时间片),于是进程
由就绪态
转换为运行态
。运行态
的进程
,在时间片用完后不得不让出处理机,从而进程由运行态
转化为就绪态
,此外在可剥夺的操作系统中,当有更高优先级
的进程就绪时,调度程度将正在执行的进程转化为就绪态
,让更高优先级
的进程执行。运行态
转换为阻塞态
,进程以系统调用
的形式请求操作系统
提供服务,这是一种特殊的由运行用户态程序
调用操作系统内核
过程的程序。进程
等待的事件到来时(如IO操作结束或中断结束时),中断处理程序
必须把相应进程的状态由阻塞态
转化为就绪态
。一个进程从
运行态
变为阻塞态
是主动行为
,而从阻塞态
变成就绪态
是被动行为
,需要其他相关进程的协助。
一般把进程控制
用的程序段称为原语
,原语
的特点是执行期间不允许中断
,它是一个不可分割的基本单位
。
创建
另外一个进程,创建者称为父进程
,被创建的进程称为子进程
。子进程
可以继承父进程
所拥有的资源,当子进程
被撤销
时,应将其从父进程
那里获得的资源归还给父进程
,此外在撤销父进程
时必须同时撤销其所有的子进程
。登录系统
、作业调度
、系统提供服务
、用户程序的请求
等都会引起新进程的创建
。操作系统会创建一个新的进程
(创建原语
):新进程
分配一个唯一的进程标识号
,并申请一个空白的PCB
(PCB是有限的)。若PCB申请失败,则创建失败。分配资源
,为新进程的程序和数据
及用户栈
分配必要的内存空间
(PCB中体现)。若资源不足,则并不是创建失败,而是处于阻塞态
,等待内存资源。初始化PCB
主要包括初始化标志信息
,初始化处理机状态信息
和初始化处理机控制信息
,以及设置进程的优先级
等。进程就绪队列
能够接纳新进程,则将新进程插入就绪队列
,等待被调度运行。引起
进程终止
的事件主要有:①
正常结束
,表示进程的任务已完成,并准备退出运行。
②异常结束
,表示进程在运行时发生了某种异常事件,使程序无法继续运行。
③外界干预
,指进程应外界的请求而终止运行。
操作系统
终止进程
过程如下(撤销原语
):①根据
被终止进程
的标识符,检索PCB,从中读出该进程的状态。②若
被终止进程
处于执行状态
,立即终止该进程的执行,将处理机资源
分配给其他进程。③若该进程还有
子孙进程
,则应将其所有子孙进程
终止。④将该进程所拥有的
全部资源
,或归还给其父进程
,或归还给操作系统
。⑤将该PCB从所在
队列(链表
)中删除
。
请求系统资源失败
,等待某种操作完成
,新数据尚未到达或无心工作可做
等),由系统自动执行阻塞原语(Block)
,使自己由运行态
变为阻塞态
,可见进程的阻塞
是进程自身的一种主动行为
,也因此只有处于运行态
的进程才可能将其转为阻塞态
阻塞原语
的执行过程如下:①找到将要
被阻塞进程
的标识号
对应的PCB
。
②若该进程为运行态
,则保护其现场,将其状态转为阻塞态
停止运行。
③把该PCB插入相应事件的等待队列
,将处理机资源
调度给其他就绪进程
当被阻塞进程
所期待的事件发生(如它所启动的IO操作
已完成,或其所期待的数据已到达)时,由有关进程
调用唤醒原语(Wakeup)
,将等待该事件的进程唤醒
。
唤醒原语
的执行过程如下:①在该事件的
等待队列
中找到相应的进程的PCB
。②将其从
等待队列
中移出,并致其状态为就绪态
。③把该PCB插入
就绪队列
,等待调度程序调度。
Block原语
和Wakeup原语
是一对作用刚好相反的原语,必须成对使用。Block原语
是被阻塞进程
自我调用实现的,而Wakeup原语
则是由一个被唤醒进程
合作或被其他相关的进程调用实现的。
通常的进程
来说,其创建
、撤销
及要求由系统设备
完成的IO操作
都是利用系统调用
而进入内核
的,再由内核中的相应处理程序予以完成。进程切换同样是在内核的支持下实现的,可以说任何竞争都是在操作系统内核
的支持下运行的,是与内核紧密相关。进程切换
是指处理机从一个进程的运行转到另一个进程上运行,在这个过程中进程的运行环境产生了实质性的变化
进程切换
的过程如下:①保存
处理机上下文
,包括程序计数器
和其他寄存器
。②更新
PCB信息
。③把进程的PCB移入相应的队列。如就绪、在某事件阻塞等队列。
④选择另一个进程执行并
更新
其PCB。⑤更新
内存管理
的数据结构
。⑥恢复处理机上下文。
进程切换
与处理机模式切换
是不同的,模式切换
时处理机逻辑上可能还在同一进程中运行。若进程因中断
或异常
进入核心态
运行,执行完后又回到用户态刚被中断的程序
运行,则操作系统只需恢复
进程进入内核时所保存的CPU现场,而无需改变当前进程的环境信息
。但若要切换进程
,当前的运行进程
改变了,则当前进程的环境信息
也需要改变。
进程
是一个独立的运行单位
,也是操作系统进行资源分配和调度的基本单位有以下三部分组成,最核心的部分是进程控制块PCB
。
存储
,并在进程结束
时删除
,PCB
是进程实体
的一部分,是进程存在的唯一标志。现行状态信息
,以便对其进行控制和管理。PCB表
来管理和控制进程
。现行状态和优先级
;在调度到某进程后,要根据其PCB所保存的处理机状态信息
,设置该进程恢复运行
的现场,并根据其PCB中的程序和数据的内存地址
找到其程序和数据。同步
、通信
或访问文件
时,也需要访问PCB。当进程由于某种原因而暂停运行时
,又需将其断点
的处理机环境
保存在PCB中。进程
的整个生命期中,系统
总是通过PCB对进程进行控制,系统唯有通过进程的PCB
才能感知到其进程的存在。PCB
主要包括进程描述
、信息进程控制
、管理信息
、资源分配清单
和处理机相关信息
等。①进程描述信息
进程标识符
:标志各个进程,每个进程都有唯一一个标识号
。
用户标识符
:进程归属的用户,用户标识符
主要为共享
和保护
服务。
②进程控制和管理信息
进程当前状态
:描述进程的状态信息
作为处理机分配调度的依据。
进程优先级
:描述进程抢占处理机的优先级,优先级高的进程可优先获得处理机。
③资源分配清单
用于说明有关内存地址空间
或虚拟地址空间
的情况,所打开文件的列表
和所使用的输入输出设备信息
。
④处理机相关信息
主要指处理机中各寄存器的值。当进程被切换时,处理机状态信息
都必须保存在相应的PCB中,以便在该进程重新执行时,能从断点
继续执行。
在一个系统中通常存在着许多进程的PCB,有的处于就绪态
,有的处于阻塞态
,而且阻塞下来的原因各不相同。
为了方便进程的调度和管理
,需要将各进程的PCB用适当的方法组织起来,目前常用的组织方式有链接方式
和索引方式
两种:
链接方式:将同一状态的PCB链接成一个队列
,不同状态对应不同的队列
,也可把处于阻塞态
的进程的PCB,根据其阻塞原因的不同,排成多个阻塞队列
。
索引方式:将同一状态
的进程
组织在一个索引表
中,索引表的表项
指向相应的PCB,不同状态对应不同的索引表,如就绪索引表
和阻塞索引表
等。
2. 程序段
程序段
就是能被进程调度程序
调度到CPU执行的程序代码段
。
程序
可被多个进程共享
,即多个进程可以运行同一个程序。
3. 数据段
一个进程的数据段
可以是进程对应的程序
加工处理的原始数据
,也可以是程序执行时产生的中间或最终结果
。
进程通信
是指进程之间的信息交换
,PV操作
是低级通信方式
,高级通信方式
是指以较高的效率传输大量数据
的通信方式,高级通信方法主要有以下三类:
直接访问
的共享空间
,通过对这片共享空间
进行读写操作
实现进程之间的信息交换
。在对共享空间
进行读写操作
时,需要使用同步互斥工具
(如PV操作),对共享空间
的读/写操作
进行控制。低级共享
是基于数据结构
的共享高级共享
是基于存储区
的共享操作系统
只负责为通信进程
提供可共享使用的存储空间
和同步互斥工具
,而数据交换
则由用户自己安排读写指令
完成注意:
用户进程空间
一般都是独立的,进程运行期间一般不能访问其他进程的空间,要想让两个用户进程共享空间必须通过特殊的系统调用实现,而进程内的线程是自然共享进程空间的。
消息传递
在消息传递系统
中,进程间的数据交换
是以格式化的消息
为单位的,如果通信的进程之间不存在可直接访问的共享空间,则必须利用操作系统提供的消息传递方法实现进程通信。
进程
通过系统提供的发送消息
和接收消息
两个原语进行数据交换
①直接通信方式
发送进程
直接把消息发送给接收进程
,并将它挂在接收进程
的消息缓冲队列
上,接收进程
从消息缓冲队列
中取得信息。
②间接通信方式
发送进程
把消息发送到某个中间实体
,接收进程
从中间实体
取得消息,这种中间实体
一般称为信箱
,这种通信方式又成为信箱通信方式
。
该通信方式广泛应用于计算机网络中,相应的通信系统
称为电子邮件系统
。
所谓“管道”
是指用于连接一个读进程
和一个写进程
,以实现它们之间的通信的一个共享文件
,又名pipe文件
。向管道(共享文件)
提供输入的发送进程(写进程)
,以字符流形式将大量的数据送入写通道
,而接收管道
输出的接收进程(读进程)
则从管道中接收(读)数据
,为了协调双方的通信,管道机制
必须提供以下三个方面的协调能力
:互斥
、同步
和确定对方存在
。
以Linux中的管道为例:
在Linux中管道是一种使用非常频繁的通信机制,从本质上说管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题:
①限制管道的大小。
实际上管道是一个固定大小的缓冲区,在Linux中该缓冲区的大小为4,kb,这是它的大小,不像稳健那样不加检验的增长,使用单个固定缓冲区也会带来问题,比如在斜管道时可能变满,这种情况发生时随后对管道的right调用将默认的被阻塞,等待某些数据被读取,以便腾出足够的空间共write调用。②独进程也可能工作的比写进程快。
当所有当前进程数据已被读取时,管道变空,当这种情况发生时,一个随后的read调用将默认的被阻塞,等待某些数据被写入,这解决了瑞的调用返回文件结束的问题。
管道
可以理解为共享存储的优化和发展
。因为在共享存储
中,若某进程要访问共享存储空间
,则必须没有其他进程在该共享存储空间
中进行写操作
,否则访问行为就会被阻塞,而管道通信中存储空间进化成了缓冲区,缓冲区只允许一边写入另一边读出,因此只要缓冲区中有数据进程就能从缓冲区中读出,而不必担心会被其他进程在另一在其中进行写操作而遭到阻塞。因为写进程会先把缓冲区写满,然后才让读进程读,当缓冲区中还有数据时写进程不会往缓冲区写数据,这也决定了管道通信必然是半双工通信。
为了更好地使多道程序并发执行
,提高资源利用率和系统吞吐量:而引入线程的目的则是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。引入线程后,进程的内涵发生了改变,进程只作为除CPU外的系统资源的分配单元,而线程则作为处理机的分配单元。由于个进程内部有多个线程,若线程的切换发生在同一个进程内部,则只需要很少的时空开销。
2)拥有资源。不论是传统操作系统还是设有线程的操作系统,进程都是拥有资源的基本单位,而线程不拥有系统资源(也有点儿必不可少的资源) ,但线 程可以访问其隶属进程的系统资源。要知道,若线程也是拥有资源的单位,则切换线程就需要较大的时空开销,线程这个概念的提出就没有意义。
3)并发性。在引入线程的操作系统中,不仅进程之间可以并发执行,而且多个线程之间也可以并发执行,从而使操作系统具有更好的并发性,提高了系统的吞吐量。
4)系统开销。由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O设备等,因此操作系统所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程CPU环境的保存及新调度到进程CPU环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。此外,由于同进程内的多个线程共享进程的地址空间,因此这些线程之间的同步与通信非常容易实现,甚至无须操作系统的干预。
5)地址空间和其他资源(如打开的文件)。进程的地址空间之间互相独立,同一进程的各线程间共享进程的资源,某进程内的线程对于其他进程不可见。
6)通信方面。进程间通信(IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性,而线程间可以直接读/写进程数据段(如全局变量)来进行通信。
多线程操作系统把线程作为独立运行(或调度)的基本单位,此时的进程已不再是一个基本的可执行实体,但它仍具有与执行相关的状态。所谓进程处于“执行”状态,实际上是指该进程中的某线程正在执行。线程的主要属性如下:
1)线程是一个轻型实体, 它不拥有系统资源,但每个线程都应有一一个唯一的标识符和一 一个线程控制块,线程控制块记录了线程执行的寄存器和栈等现场状态。
2)不同的线程可以执行相同的程序,即同-个服务程序被不同的用户调用时,操作系统把它们创建成不同的线程。
3)同一进程中的各个线程共享该进程所拥有的资源。
4)线程是处理机的独立调度单位,多个线程是可以并发执行的。在单CPU的计算机系统中,各线程可交替地占用CPU;在多CPU的计算机系统中,各线程可同时占用不同的CPU,若各个CPU同时为一个进程内的各线程服务,则可缩短进程的处理时间。
5)一个线程被创建后,便开始了它的生命周期,直至终止。线程在生命周期内会经历阻塞态、就绪态和运行态等各种状态变化。
为什么线程的提出有利于提高系统并发性?可以这样来理解:由于有了线程,线程切换时,有可能会发生进程切换,也有可能不发生进程切换,平均而言每次切换所需的开销就变小了,因此能够让更多的线程参与并发,而不会影响到响应时间等问题。
4. 线程实现方式
线程的实现可以分为两类:用户级线程(User-Level Thread, ULT)和内核级线程(Kermel-Level Thread, KLT)。内核级线程又称内核支持的线程。
在用户级线程中,有关线程管理(线程的创建、城消和切换等)的所有工作都由应用店成,内核意识不到线程的存在。应用程序可以通过使用线程库设计成多线程程序。序从单线程开始,在该线程中开始运行,在其运行的任何时刻,可以通过调用线程库中的派生例程创建一个在相同进程中运 行的新线程。图251a)说明了用户级线程的实现方式。
在内核级线程中,线程管理的所有工作由内核完成,应用程序没有进行线程管理的代码,只有一个到内核级线程的编程接口。内核为进程及其内部的每个线程维护上下文信息,调度也在内核基于线程架构的基础上完成。图2.5(b)说明了内核级线程的实现方式。
有些系统中使用组合方式的多线程实现。线程创建完全在用户空间中完成,线程的调度和同步也在应用程序中进行。一个应用程序中的多个用户级线程被映射到一些(小于等于用户级线程的数目)内核级线程上。图2.5©说明了用户级与内核级的组合实现方式。
1)多对一模型
将多个用户级线程映射到一个内核级线程,线程管理在用户空间完成。此模式中,用户级线程对操作系统不可见(即透明)。
优点:线程管理是在用户空间进行的,因而效率比较高。
缺点:一个线程在使用内核服务时被阻塞,整个进程都会被阻塞:多个线程不能并行地运行在多处理机上。
2)一对一模型
将每个用户级线程映射到一个内核级线程。
优点:当一个线程被阻塞后,允许另一个线程继续执行,所以并发能力较强。
缺点:每创建一个用户级线程都需要创建一个内核级线程与其对应,这样创建线程的开销比较大,会影响到应用程序的性能。
3)多对多模型
将n个用户级线程映射到m个内核级线程上,要求m≤n。
特点:多对多模型是多对一模型和一 对一模型的折中,既克服了多对模型 并发度不高的缺点,又克服了一对一模型的一个用户进程占用太多内核级线程而开销太大的缺点。此外,还拥有多对一模型和一对一模型各自的优点。
1)为什么要引入进程?
在多道程序同时运行的背景下,进程之间需要共享系统资源,因此会导致各程序在执行过程中出现相互制约的关系,程序的执行会表现出间断性的特征。这些特征都是在程序的执行过程中发生的,是动态的过程,而传统的程序本身是一组指 令的集合,是一 一个静态的概念,无法描述程序在内存中的执行情况,即我们无法从程序的字面上看出它何时执行、何时停顿,也无法看出它与其他执行程序的关系,因此,程序这个静态概念已不能如实反映程序并发执行过程的特征。为了深刻描述程序动态执行过程的性质乃至更好地支持和管理多道程序的并发执行,人们引入了进程的概念。
2)什么是进程?进程由什么组成?
进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一 一个活动的实体。它不只是程序的代码本身,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。
一个进程实体由程序段、相关数据段和PCB三部分构成,其中PCB是标志一个进程存在的唯一标识,程序段是进程运行的程序的代码,数据段则存储程序运行过程中相关的一些数据。
3)进程是如何解决问题的?
进程把能够识别程序运行态的一些变量存放在PCB中,通过这些变量系统能够更好地了解进程的状况,并在适当时进行进程的切换,以避免一些资源的浪费,甚至划分为更小的调度单位一线程来提高系统的并发度。