第二章 进程的描述与控制
前言
操作系统所具有的四大特征都是基于进程形成的,并从进程的角度对操作系统进行研究。因此进程是一个极其重要的概念。
2.1、程序执行
2.1.1 程序顺序执行
一个程序通常由几个程序段组成,每个程序段完成特定功能,它们在执行时,需按照某种先后次序顺序执行,仅当前一段程序执行完后,才运行后一段。
程序顺序执行时特征:
- 顺序性:处理机的操作严格按照程序所规定的顺序执行,即每一操作必须在下一操作开始之前结束(或者说下一操作必须在当前操作结束后才能开始)。
- 封闭性:程序是在封闭的环境下执行的。即
●程序运行时独占全机资源,资源的状态(除初始态外)只有本程序才能改变它。
●程序一旦开始执行,其执行结果不受外界影响。 - 可再现性:只要程序执行时的环境和初始条件相同,当程序重复执行时,都将获得相同的结果。
2.1.2 程序并发执行
顺序执行时,系统资源的利用率很低,因此引入多道程序技术,使程序或程序段之间能并发执行。但只有在不存在前趋关系的程序之间才有可能并发执行,否则无法并发执行。
程序并发执行时的特征:
- 间断性:程序在并发执行时,由于它们共享系统资源,以及为完成同一任务而相互合作,致使这些并发执行的程序之间形成了相互制约的关系(互斥关系、同步关系)。导致“执行—暂停—执行”这种间断性的活动规律
- 失去封闭性:程序在并发执行时,由于多个程序共享系统资源,因而这些资源的状态将由多个程序来改变,致使程序的运行已失去了封闭性。即某程序的执行时,会受到其他程序的影响。
- 不可再现性(与时间有关的错误):程序在并发执行时,由于失去了封闭性,也将导致其再失去可再现性。
2.2 进程的描述
2.2.1 进程的定义和特征
在多道程序环境下,程序的执行属于并发执行,此时它们将失去其封闭性,并具有间断性,以及其运行结果不可再现性的特征。为使程序并发执行,并且对并发执行的程序加以描述和控制,人们引入“进程”。
进程的定义:进程是程序在一个数据集上的运行过程,是系统进行资源分配和调度的一个独立单位。 (传统OS的定义)
通常的程序是不能并发执行的,为使程序(含数据)能独立运行,应为之配置一进程控制块(即PCB:描述进程的基本情况和活动过程)。
结构组成:程序段、相关的数据段、PCB三部分构成了进程实体(简称进程)。
eg.创建进程,实质上是创建进程实体中的PCB;撤销进程,实质上是撤销进程中的PCB。
进程的特征:
- 动态性:进程的实质是进程实体的一次执行过程,故动态性是进程的最基本特征。 程序则是一组有序指令的集合,并存放在某种介质上,其本身不具有活动的含义,因而是静态的。
- 并发性:这是指多个进程实体同存于内存中,且能在一段时间内同时运行。
- 独立性:在传统的OS中,独立性是指进程实体是一个能独立运行、独立分配资源和独立接受调度的基本单位。
- 异步性:是指进程按各自独立的、不可预知的速度向前推进,或说进程实体按异步方式运行。
2.2.2 进程的基本状态及转换
进程的三种基本状态:
- 就绪(Ready)状态:当进程已分配到除CPU以外的所有资源后,只要再获得CPU,便可立即执行,进程这时的状态称为就绪状态。 系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。
- 执行(Running)状态:进程已获得CPU,其程序正在执行。
- 阻塞(Block)状态(自我阻塞):正在执行的进程由于发生某事件而暂时无法继续执行时,便放弃处理机而处于暂停状态,亦即进程的执行受到阻塞,把这种暂停状态称为阻塞状态(或等待状态)。 使进程阻塞的典型事件:请求I/O,申请缓冲空间等等。
三种基本状态的转换:
创建状态和终止状态:为满足PCB对数据及操作的完整性要求以及增强管理的灵活性。通常在系统中又为进程引入了两种常见的状态。
- 创建状态:创建进程①申请空白PCB,并向PCB中填写用于控制和管理进程的信息;②为该进程分配运行时所必须的资源;③将该进程转入就绪状态并插入就绪队列中。但进程所需资源尚不能满足时,不能被调度时所处的状态为创建状态。
- 终止状态:终止进程①等待OS进行善后处理;②将PCB清零,并将PCB控件返还系统。当一个进程到达了自然结束点,或是出现了无法克服的错误,或是被OS终结,它将进入终止状态。
挂起操作:为了系统和用户观察和分析进程的需要。当该操作作用于某进程时,该进程处于静止状态。与其对应的是激活操作。挂起原语:Suspend;激活原语:Active
状态转换:
- 活动就绪→静止就绪
- 活动阻塞→静止阻塞
- 静止就绪→活动就绪
- 静止阻塞→活动阻塞
2.2.4 进程管理中的数据结构
本节着重介绍PCB(进程表)
PCB作用:使一个在多道程序环境下不能独立运行的程序(含数据),成为一个能独立运行的基本单位,一个能与其它进程并发执行的进程。或者说,OS是根据PCB来对并发进程进行控制和管理的。 PCB是进程存在的唯一标志
- 作为独立运行基本单位的标志:PCB是进程存在于系统的唯一标志。
- 能实现间断性运行方式:可以将CPU现场信息保存在PCB中
- 提供进程管理所需要的信息:程序、数据和文件的地址信息等
- 提供进程调度所需要的信息:进程的状态和优先级等
- 实现与其他进程的同步与通信:信号量及通信队列指针等
PCB中的信息:
- 进程标识符:内部标识符(进程号):为方便系统对进程的使用(通常为进程的序号);外部标识符(名):方便用户对进程的访问。
- 处理机状态:处理机状态信息主要由处理机的各种寄存器中的内容组成的。寄存器包括:通用寄存器、指令计数器、程序状态字(PSW)寄存器、用户栈指针。(保护、恢复现场)
- 进程调度信息:
★进程状态——作为调度和对换时的依据。
★进程优先级——由于描述进程使用处理机的优先级别的一个整数,优先级高的进程优先获得处理机。
★进程调度所需的其它信息——它们与所采用的进程调度算法有关。
★事件——即阻塞原因。 - 进程控制信息:
▲程序和数据的地址——指程序和数据所在的内存或外存首地址;
▲进程同步和通信机制——如信号量、消息队列指针等,它们可能全部或部分地存放在PCB中;
▲资源清单——是一张列出了除CPU外的、进程所需的全部资源及已经分配到该进程的资源的清单;
▲链接指针——它给出本进程(PCB)所在队列中下一个进程的PCB的首址。
PCB的组织方式:
- 线性方式(适合进程数目不多的系统):优:实现简单、开销小;缺:每次查找时都需要扫描整张表
- 链接方式:把具有同一状态的PCB,用其中的链接字链接成一个队列。形成:就绪队列、阻塞队列、空白队列等
- 索引方式:系统根据所有进程的状态建立几张索引表。如 就绪索引表 、阻塞索引表等
▲索引表的首址记录在专用单元中;
▲每个索引表的表目中,记录具有相应状态的某个PCB的首址。
习题:1.对进程的管理和控制使用(原语);
2.通常,用户进程被建立后 (随着作业【程序】运行正常或不正常结束而撤销 );
2.3 进程控制
进程控制是进程管理中最基本的功能。
进程控制包括:
- 创建进程
- 终止进程
- 进程状态转换
进程控制是由OS的内核完成的,其操作一般都是原语操作
2.3.1 OS内核(一些功能模块)
为了OS及关键数据(如PCB)的安全,通常将处理机的执行状态分为系统态和用户态。
系统态:又称管态,也称内核态。具有较高特权,能执行一切指令,访问所有寄存器和存储区,传统OS都在系统态运行。
用户态:又称目态。具有较低特权的执行状态,仅能执行规定的指令,访问指定的寄存器和存储器。一般情况下,应用程序只能在用户态运行,不能去执行OS指令及访问OS区域(防止对OS破坏)。
OS的两大方面功能:
- 支撑功能
(1) 中断处理:内核最基本功能,OS赖以活动的基础
(2) 时钟管理
(3) 原语操作(原子操作):由若干条指令组成,用于完成一定功能的一个过程。不允许被中断。 - 资源管理功能:进程管理,存储器管理,设备管理
2.3.2 进程创建
在OS中允许一个进程创建另一个进程,称父进程创建子进程,子进程仍可以创建孙进程,从而形成一个家族树。子进程可以继承父进程所拥有资源,子进程撤销资源归还;父进程撤销,同时必须撤销其所有子进程。Windows中不存在任何进程层次概念,所有进程具有相同地位,但创建进程会获得一个句柄来控制子进程。
引起创建进程的事件:①用户登录②作业调度③提供服务④应用请求
进程的创建(创建原语Create()):①申请空白PCB ②为新进程分配其运行所需资源(主要为内存空间) ③初始化PCB:初始化标识符、初始化处理机状态信息、初始化处理机控制信息④新进程插入就绪队列(如果可以接纳)
2.3.3 进程终止
引起进程终止的事件:
- 正常结束:(任何)系统会有一个表示进程已经运行完成的指示
- 异常结束:进程运行时发生某种异常事件,如越界错、保护错、非法指令、特权指令、运行超时、等待超时、I/O故障。
- 外界干预:操作员或操作系统干预、父进程请求、因父进程终止
进程的终止过程(OS调用终止原语):
- 根据标识符,检索出PCB,读取该进程状态
- 若为执行状态,立即终止
- 若有子孙进程,也都立即终止
- 终止进程全部资源归还父进程或归还系统
- 终止进程PCB从队列移除
2.3.4 进程的阻塞与唤醒
引起阻塞和唤醒的事件:请求系统服务、启动某种操作、新数据未到、无新工作可做
阻塞与唤醒必须成对使用
阻塞过程:调用阻塞原语block()把自己阻塞(主动行为)。先立即停止执行,将PCB状态改为阻塞,将PCB插入阻塞队列,最后转调度程序进行重新调度,将处理机分配。
唤醒过程:调用唤醒语句wakeup(),将等待进程的事件进行唤醒。首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB中的现行状态由阻塞改为就绪,然后将该PCB出入到就绪队列。
2.3.5 进程的挂起与激活
挂起过程(原语suspend()):①检查被挂起进程的状态:若处于活动就绪或执行状态,则将其转为静止就绪;若处于活动阻塞,则将其转为静止阻塞。②把该进程的PCB复制到某指定内存区域 。③若该进程正在执行,则转进程调度程序重新调度。
激活过程(原语active()):①将进程从外存调入内存;②检查该进程现行状态,若是静止就绪,则改为活动就绪; 若是静止阻塞,则改为活动阻塞。③若采用的是抢占式调度策略,则应检查被激活就绪进程的优先级,若其优先级比先行执行进程高,则应将处理机分配给被激活进程
2.4 进程同步
进程同步的主要任务是对多个相关进程在执行次序上进行协调,以使并发执行的诸进程之间能有效的共享资源和相互合作,从而使程序的执行具有可再现性。在多道程序中,必须引入进程同步机制。
2.4.1 进程同步基本概念
两种形式的制约关系:① 间接制约关系(互斥):打印机,源于资源共享;②直接制约关系(同步):源于进程间的合作
临界资源:在一段时间内只允许一个进程访问的资源,即仅当一个进程访问完并释放该资源后,才允许另一个进程访问的资源,称为临界资源或独占资源。 例如:打印机、磁带机、共享变量
生产者—消费者问题(经典的进程同步问题):一次只能放一个产品;一次只能取走一个产品;缓冲区满则生产者不能放产品;缓冲区空则消费者不能取产品。
临界区:每个进程中访问临界资源的那段代码称为临界区。若能保证诸进程互斥地进入自己的临界区,便可实现诸进程对临界区的互斥访问。
每个进程在进入临界区之前,应先对欲访问的临界资源进行检查。临界区前增加一段用于上述检查的代码,把这段代码称为进入区;相应地,在临界区后面也要加上一段称为退出区(的代码,用于将临界区正被访问的标志恢复为未被访问的标志。
为了实现各进程互斥地进入自己的临界区,一般是在系统中设置专门的同步机制来协调各进程间的运行。
同步机制应遵循的规则:
- 空闲让进:当无进程处于临界区时,表明临界资源处于空闲状态,应允许一个请求进入临界区的进程立即进入自己的临界区,以便有效地利用临界资源。
- 忙则等待:当已有进程进入临界区时,表明临界资源正在被访问,因而其他试图进入临界区的进程必须等待,以保证对临界资源的互斥访问。
- 有限等待:对要求访问临界资源的进程,应保证在有限时间内能进入自己的临界区,以免陷入“死锁”状态。——不死等。
- 让权等待:当进程不能进入自己的临界区时,应立即释放处理机,以免进程陷入“忙等”。——不忙碌等待。(eg.阻塞)
临界区的执行可以被中断;
若系统中有五个并发进程涉及某个相同的变量A,则变量A的相关临界区最少是由___5个___临界区构成。 解释:五个并发进程都涉及了变量A,每一个进程中都有访问变量A的代码,所以每个进程都有相关临界区,所以是5个。
硬件同步机制:软件方法解决进程互斥进入临界区的问题有一定难度,且存在较大局限性。因此现在计算机提供一些特殊的硬件指令来解决临界区问题。
- 关中断:实现互斥最简单的方法之一,在进入锁测试之前关闭中断,直到完成锁测试并上锁后才打开中断。进程在临界区执行期间,计算机系统不会响应中断,从而不发生调度。
- 利用Test-and-Set指令实现互斥:一条原语
- 利用Swap指令实现互斥:每个临界资源设置一个全局布尔类型变量
2.4.3 信号量机制
信号量(Semaphores)机制是一种卓有成效的进程同步工具。信号量机制已被广泛应用于单处理机和多处理机系统以及计算机网络中。
信号量是被保护的数据结构。除信号量的赋初值外,信号量的值仅能由两个同步原语改变。这两个同步原语命名为“P操作(又称wait操作)”和“V操作(又称signal操作)”
- 整型信号量
定义一个整型量S,除初始化外,仅能通过两个标准的原子操作(原语)wait(S)和signal(S)来访问。
- 记录型信号量
需要一个用于代表临界资源数目的整型变量value;还要一个在该资源上阻塞的队列(链表)指针L)。信号量除初始化外,只能通过两个原子操作(称为原语)wait(S)和signal(S)来访问。
信号量结构为:
对信号量S的每次wait操作,意味着进程请求一个该类临界资源,因此描述为S.value=S.value-1;当S.value<0时,表示该类资源已分配完,因此进程应调用block原语进行自我阻塞,放弃处理机,并插入到信号量链表S.L(阻塞队列)中。可见该机制遵循了“让权等待”准则。signal操作与之相反。
▲S.value的初值表示系统中某类资源的数目。——资源信号量。
▲S.value的初值为1,表示只允许一个进程访问,此时信号量转化为互斥信号量。
wait和signal操作的物理意义:
- Wait操作是申请资源的操作,是减1的操作。
- Signal操作是释放资源的操作,是加1的操作
- 一般每一类资源对应一个信号量
- 整型变量代表了可用资源的数目
- 等待队列里链接的是等待使用这种资源的进程
- 整型变量的值如果大于零,代表有多个资源可用。
- 整型变量的值如果等于零,代表无可用资源。
- 整型变量的值如果小于零,代表有进程在等待资源,整型变量的绝对值等于等待队列中进程的数目。
以上的进程互斥问题,是针对各进程之间要共享一个临界资源而言的。在有些应用场合,是一个进程需要先获得两个或更多的共享资源后,方能执行其任务。在有些应用场合,是一个进程需要先获得两个或更多的共享资源后,方能执行其任务
- AND型信号量
思路:将进程在整个运行过程中需要的所有资源,一次性全部地分配给进程,待进程使用完成后再一起释放。
采取原子操作方式:要么全部分配给进程,要么一个也不分配。
P、V操作:
- 信号量集
思路:若进程一次需要申请多类临界资源,每类临界资源申请多个,并且进行临界资源分配时,先测试各类临界资源是否大于其下限值。若低于下限值,则不予分配
P、V操作:
S为信号量,d为需求值,t为下限值
例题:
- 有m个进程,共享一个资源,信号量范围[1-m,1]
- 若P、V操作的信号量S初值为2,当前值为-1,则表示有___1___等待进程。 解:信号量S表示的是可用的资源数。初值为2,表示初始时有2个可用的资源。现在为-1,说明除了那2个可用资源已经被占用外,而且有一个进程在等待资源。
- 用P、V操作管理临界区时,信号量的初值应定义为(1)。一般同步为0,互斥为1
- 对于两个并发进程,设互斥信号量为mutex,若mutex=O,则_________。
一个进程进入临界区,另一个进程等待进入 或 一个进入,一个退出
2.4.4 信号量应用
-
利用信号量实现进程互斥
方法:为临界资源设置一个互斥信号量mutex,其初值为1;各进程访问该资源的临界区置于wait(mutex)和signal(mutex)之间即可。
例子:
mutex取值范围为(-1,0,1),当mutex=1,表示两个进程皆未进入需要互斥的临界区;mutex=0,表示一个在临界区运行,一个必须等待,挂入阻塞队列;mutex=-1,表示一个在临界区运行,另一个因等待而阻塞在信号量队列中,需要被当前在临界区运行的进程退出时唤醒。
signal与wait必须成对出现,缺少wait不能保证对临界资源的互斥访问;缺少signal将使临界资源永远不被释放,使得阻塞进程不能被唤醒。 -
利用信号量实现进程同步
-
利用信号量实现前趋关系
例题.
2.4.5 管程机制
使用信号量来处理进程同步问题时,由于P、V操作分散在各个进程中,给程序的维护和修改带来麻烦,而且会因同步操作的使用不当造成死锁。
管程是实现进程同步的另一有效工具,一个管程定义一个数据结构能为并发进程在其上执行的一组操作,这组操作能使进程同步和改变管程中的数据。
管程具有以下特征:
- 管程内部的局部数据结构只能被管程内定义的过程所访问,不能被管程外部的过程直接访问。
- 进程要想进入管程,必须调用管程内的某个进程
- 一次只能有一个进程在管程内执行,而其余调用该管程的进程都被挂起,等待该管程成为可用为止,即管程能有效地实现互斥。
解决信号量问题步骤:
- 确定进程(几个,是什么)
- 活动(进程干什么的):找动词、动作
- ①互斥②同步③资源管控 进程间找关系
- 信号量(加入信号量)
例题1:图书馆规定,每位进入图书馆的读者要在登记表上登记,退出时要在登记表上注销。(1)用信号量实现读者之间的互斥登记和注销。(2)图书馆共有100个座位,当图书馆中没有空座位时,后到的读者在图书馆要等待(阻塞) mutex记录型信号量
例题2: 一家四人父、母、儿子、女儿围桌而坐;桌上有一个水果盘; 当水果盘空时,父亲可以放香蕉或者母亲可以放苹果,但盘中已有水果时,就不能放,父母等待。当盘中有香蕉时,女儿可吃香蕉,否则,女儿等待;当盘中有苹果时,儿子可吃,否则,儿子等待。
semaphore S1,S2,S3
S1.value = 1 , S2.value = 0 ,S3.value = 0
father(){ mother(){ daughter(){ son(){
P(S1) P(S1) P(S2) P(S2)
放香蕉 放苹果 吃香蕉 吃苹果
V(S2) V(S3) V(S1) V(S1)
}
例题3:有一个超市,最多可容纳N个人进入购物,当N个顾客满员时,后到的顾客在超市外等待;超市中只有一个收银员。可以把顾客和收银员看作两类进程,两类进程间存在同步关系。写出用P;V操作实现的两类进程的算法
semaphore S,C(顾客与收银员的同步信号量),
S.value=0 , C.value=0
收银员(){ 顾客(){
P(S) P(N)
收银 购物
V(C) V(S)
P(C)
} V(N)
2.5 经典同步问题
- 生产者-消费者问题
从特殊到一般(从易到难)可以分3种形式:
①一个生产者、一个消费者、一个缓冲区的问题
方法:
(1).设置1个信号量empty,其初值为1,表示有1个空缓冲区;设置1个信号量full,其初值为0,表示开始时没有空缓冲区;(由物理意义确定)
(2).生产者将产品存入缓冲区之前,应先测试缓冲区是否空:执行wait(empty)操作;离开临界区(存入产品)后,应通知(可能会唤醒)消费者:执行signal(full)操作;
(3).消费者从缓冲区取产品之前,应先测试缓冲区是否满:执行wait(full)操作;离开临界区(取走产品)后,应通知(可能会唤醒)生产者:执行signal(empty)操作
代码:
struct semaphore empty,full;
empty.value=1;full.value=0;
parbegin
process Producer() process Consumer()
{ ... {
produce an item in nextp; wait(full); //测试
wait(empty);//测试 nextc=buffer;
buffer=nextp; signal(empty);//通知
signal(full);//通知消费者 consume the item in nextp;
} }
②. 一个生产者、一个消费者、n个缓冲区的P-C问题
方法与1类似
③. k个生产者、m个消费者、n个缓冲区的问题
方法思路:
◆用互斥信号量mutex对缓冲区(共享变量in和out)的互斥使用,互斥信号量mutex初值为1;
◆用资源信号量empty表示多缓冲中空缓冲区的数目,empty的初值为n;
◆用资源信号量full表示多缓冲中满缓冲区的数目,full的初值为0;
◆只要多缓冲未满,生产者便可将消息送入缓冲区;
◆只要多缓冲不空,消费者便可从缓冲区取走一个消息。
◆生产者用共享变量in作为下标访问缓冲区,mutex为其互斥信号量;消费者用共享变量out作为下标访问缓冲区,其互斥信号量也用mutex。
-
哲学家进餐问题
问题描述:有5个哲学家共用一张圆桌,分别坐在周围的5张椅子上,在圆桌上有5个碗和5只筷子,他们的生活方式是交替地进行思考和进餐。平时,每个哲学家进行思考,饥饿时便试图拿起其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐完毕,放下筷子继续思考。如图:
思路:利用记录型信号量解决。桌子上的筷子f0,f1,…,f4是临界资源,应互斥使用,可用一个信号量表示一只筷子,5只筷子的5个信号量构成信号量数组,所有信号量的初值均为1。
此算法虽然能保证相邻哲学家对筷子的访问互斥,但可能引起死锁(两个哲学家拿同一根筷子)
解决方案:
(1)至多允许4个哲学家同时取左边的筷子,这样能至少保证一个哲学家能就餐,并在用毕后释放他用过的两只筷子,从而使更多的哲学家能够进餐。 (其他代码不变,将进程变为4个即可)
(2)仅当哲学家左右两只筷子均可用时,才允许他拿起筷子进餐。(用AND信号量机制)
(3)规定奇数号哲学家先拿左边筷子,然后再拿右边筷子;而偶数号哲学家先拿右边筷子,然后再拿左边筷子。即五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获得两支筷子而进餐
(4)规定每个哲学家先拿序号小的筷子——按序号分配。 -
读者-写者问题
要求:
◆允许多个读者进程同时读一个共享文件,因为读操作不会使数据文件混乱;
◆不允许两个或两个以上写者进程同时访问共享文件,因为这种访问将会引起混乱;
◆不允许一个写者进程和其他读者进程同时访问共享文件,因为这种访问将会引起混乱。
读者-写者问题从特殊到一般(从易到难)可以分3种形式:一读一写,一读多写,多读多写
思路分析:
▲ 为实现Reader进程和Writer进程间的互斥,设置一个互斥信号量Wmutex,其初值为1;
▲ 设置一个整型变量Rcounter,记录正在读的读者进程数。其初值为0;
▲ 由于只要有一个Reader进程在读,便不允许Writer进程去写,因此第一个读者进程需要执行wait(Wmutex)操作,即当Rcounter =0时,Reader进程才需要执行wait(Wmutex)操作。若wait(Wmutex)操作成功(表示此时无Writer进程在写),Reader进程便可去读,同时做Rcounter+1的操作。若wait(Wmutex)操作成功(表示此时无Writer进程在写),Reader进程便可去读,同时做Rcounter+1的操作。
▲ 同理,最后一个Reader进程离开时(Rcounter-1后变为0)应执行signal(mutex)操作,以便让Writer进程写。
▲ Rcounter是被多个Reader进程访问的临界资源,为了对它互斥访问,应为它设置一个互斥信号量Rmutex。
▲mutex用于写者优先策略,在写者等待时,禁止新来读者进入。
semaphore Wmutex,Rmutex,mutex;
int Rcounter = 0;
Wmutex.value=Rmutex.value=1;
parbegin
process Readeri (i = 1,2,…) process Writer()
{ {
wait(mutex); wait(mutex);
wait(Rmutex); wait(Wutex);
if(Rcounter==0) wait(Wmutex); Writing;
Rcounter = Rcounter + 1; signal(Wutex);
signal(Rmutex); siganl(mutex);
signal(mutex);
…
Reading;
…
wait(Rmutex);
Rcounter = Rcounter – 1;
if(Rcounter==0)signal(Wmutex);
signal(Rmutex);
}
习题:有一座东西方向的独木桥;用P,V操作实现:
(1) 每次只允许一个人过桥;
(2) 当独木桥上有行人时,同方向的行人可以同时过桥,相反方向的人必须等待。
(3) 当独木桥上有自东向西的行人时,同方向的行人可以同时过桥,从西向东的方向,只允许一个人单独过桥。
设信号量 MUTEX=1
P (MUTEX)
过桥
V (MUTEX)
(2)解
设信号量: MUTEX=1 (东西方互斥)
MD=1 (东向西使用计数变量互斥)
MX=1 (西向东使用计数变量互斥)
设整型变量: CD=0 (东向西的已上桥人数)
CX=0 (西向东的已上桥人数)
从东向西:
P (MD)
IF (CD=0)
{P (MUTEX) }
CD=CD+1
V (MD)
过桥
P (MD)
CD=CD-1
IF (CD=0)
{V (MUTEX) }
V (MD)
————————————————
从西向东:
P (MX)
IF (CX=0)
{P (MUTEX) }
CX=CX+1
V (MX)
过桥
P (MX)
CX=CX-1
IF (CX=0)
{V (MUTEX) }
V (MX)
(3) 解:从东向西的,和(2)相同;从西向东的和(1)相同。
2.6 进程通信
进程通信是指进程之间的信息交换。
进程之间的互斥和同步,交换的信息量少——低级通信。
信号量机制作为通信工具不够理想,表现在: 效率低; 通信对用户不透明
在进程之间要传送大量数据时,应当利用OS提供的高级通信工具,该工具的主要特点是:
- 使用方便,通信过程对用户是透明的。大大减少了通信程序编制上的复杂性
- 高效地传送大量数据。用户可直接利用高级通信命令(原语)高效地传送大量数据。
2.6.1 进程通信的类型
目前高级通信机制可分为四大类:共享存储器系统、管道通信系统、消息传递系统、客户机-服务器系统。
- 共享存储器系统【单机(集中式)】
又分为两种类型:
①基于共享数据结构的通信方式:如生产者-消费者问题中,是用有界缓冲区这种数据结构来实现通信的。公用数据结构的设置及对进程间同步的处理,都是程序员的职责,增加了程序员的负担,而操作系统只需提供共享存储器。——低效的通信方式(低级通信)
②基于共享存储区的通信方式:在存储区中划出一块共享存储区,诸进程可通过对共享存储区中数据的读和写来实现通信。——属于高级通信方式。 - 管道(pipe)通信(高级)
管道:用于连接一个读进程和一个写进程以实现它们之间通信的一个共享文件,又称pipe文件。
特点:◆写进程以字节流的形式将大量数据送入管道; ◆读进程从管道中接收(读)数据。
为协调读写双方的通信,管道机制必须提供以下三方面的协调能力:
★互斥——当一个进程正在对pipe执行读/写操作时,其它进程必须等待;
★同步——当写进程把一定数据写入pipe,便去睡眠等待,直至读进程取走数据后,再把它唤醒;当读进程读一空pipe时,也应睡眠等待,直至写进程将数据写入pipe后,再把它唤醒。
★确定对方是否存在——只有确定对方以存在时,才能进行通信。
-
消息传递系统
单机系统、多机系统、计算机网络,用得最广泛的一种高级通信机制。
特点:
●进程间的数据交换,是以格式化的消息(message)为单位的。
●计算机网络中,message又称为报文。
●利用系统提供的一组通信命令(原语)进行通信。
● OS隐蔽了通信实现细节,大大简化了通信程序编制的复杂性,因而得到广泛应用。
数据 —封装—》消息(单位)—一组通信命令(原语)—》交换。
通信方式分为:
①直接通信方式:发送进程利用OS所提供的的发送原语,直接把消息发送给目标进程;
②间接通信方式:发送和接收进程,都通过共享中间实体(邮箱)的方式进行消息的发送和接收。 -
客户机-服务器系统
客户机-服务器系统的通信机制,在网络环境的各种应用领域已成为当前主流的通信实现机制。
主要包括:
①套接字:一个套接字就是一个通信标识类型的数据结构,是进程通信和网络通信的基本构件。套接字又包含两类:(1)基于文件型:同一台主机环境,一个套接字关联一个特殊文件,通信双方通过对这个特殊文件的读写实现通信,类似管道。 (2)基于网络型:非对称方式通信(即发送者需要提供接受者命名),不同主机的网络环境,被分配一对套接字,一个属于接收进程(或服务器),一 个属于发送进程(或客户端)。 套接字优势在于:不仅适用于同一台计算机内部的进程通信,也适用于网络环境中不同计算机见的进程通信。每个套接字拥有唯一的套接字号(套接字标识符),确保通信双方之间逻辑链路的唯一性。隐藏了通信设施及实现细节,采用统一接口处理。
②远程过程调用和远程方法调用:允许一台主机系统上进程调用另外一台主机系统上的进程 , 程序员表现为常规的过程调用,无需额外地为此编程。如果涉及的软件采用面向对象编程,远程过程调用亦可以成为远程方法调用。
2.6.2 消息传递通信的实现方式
- 直接通信方式 :是指发送进程利用OS所提供的命令,直接把消息发送给目标进程。
1)直接通信原语
①对称寻址:要求发送和接收进程都以显式方式提供对方的标识符。两条通信原语为:send(receiver,message)发送一个消息给接收进程;receive(sender,message)接收Sender发来的消息。 不足:一旦改变进程的名称,则可能需要检查所有其他进程的定义。不利于模块化。
②非对称寻址方式:有时,接收进程可能与多个发送进程通信,故不可能事先知道发送进程。对于这样的应用,接收原语中的源进程参数,是完成通信后的返回值。接收原语可表示为:
receive(id,message); id是返回值(标识符)
2)消息的格式
必须具有一定的消息格式,在单机系统环境中(en相同),消息格式较为简单,可采用比较短的定长消息格式,以减少对消息的处理和存储开销。-----方便用户
3)进程的同步方式
进程之间通信,同样需要进程同步机制,以协调通信
4)通信链路
两进程之间必须建立一条通信链路 - 信箱通信(间接通信方式):指进程之间的通信,需要通过作为共享数据结构的实体——信箱。该实体建立在随机存储器的公共缓冲区。
▲信箱暂存发送进程发送给目标进程的消息;
▲ 接收进程从信箱中取出对方发给自己的消息。
既可实现实时通信,也可实现非实时通信。
信箱通信原语:
(1)信箱的创建和撤消。信箱可由OS创建,也可由用户用OS命令创建。
(2)消息的发送和接收。
send(mailbox,message);
receive(mailbox,message)
2.6.3 直接消息传递系统实例
消息传递系统实现中的进程同步方式 :
消息缓冲队列通信机制中的数据结构:
2.7 线程的基本概念
20世纪60年代人们提出了进程概念后,在OS中一直都是以进程为能拥有资源和独立运行的基本单位,从而解决单处理机环境下的程序并发执行问题。
80年代中期,人们提出比进程更小的能独立运行的基本单位——线程。
线程能比进程更好地提高程序的并发执行程度,改善OS性能
2.7.1 线程的引入
OS引入线程,目的是减少程序在并发执行时所付出的时空开销。
进程的两个基本属性:①进程是一个可拥有资源的独立单位 ②进程同时又是一个可独立调度和分派的基本单位。
进程“太重”,系统在进程上所花的时空开销大致表现在:
- 创建进程:系统在创建进程时必须为它分配除CPU以外的所有资源,如内存空间、I/O设备,以及建立相应的PCB。
- 撤销进程:系统撤消进程时,必须先回收其所占的资源,然后在撤消PCB。
- 进程切换:进程切换时,由于要保留当前进程的CPU环境和设置新进程的CPU环境,因而需花费不少处理机时间。
总之,由于进程是一个资源拥有者,因而在创建、撤消、切换中,系统必须为之付出较大的时空开销,故系统中的进程数目不宜过多,进程切换的频率也不宜过高,这限制了并发程度的进一步提高。
线程只作为调度和分派的基本单位,而不作为资源分配的基本单位。一个进程通常包括多个线程。
线程的属性:每个线程都作为分配CPU的基本单位,是花费最小开销的实体。
2.7.3 线程的状态和线程控制块
- 线程运行的三个状态:
(1)执行状态:表示线程已获得处理机而正在运行
(2)就绪状态:指线程以具备了各种执行条件,只须获得CPU即可立即执行
(3)阻塞状态:指线程在执行中因某事件受阻而处于暂停状态
线程状态之间转换与进程的一样。 - 线程控制块TCB
在OS中的每一个线程都可以用线程标识符和一组状态参数进行描述
状态参数包括:
- 寄存器状态:程序计数器PC和堆栈指针内容
- 堆栈:通常保存局部变量和返回地址
- 线程运行状态:执行状态、就绪状态、阻塞状态
- 优先级
- 线程专用存储器:用于保存线程自己的局部变量拷贝
- 信号屏蔽:对某些信号加以屏蔽
线程间的同步和通信:互斥锁(mutex)、条件变量(管程)、信号量机制
2.8 线程的实现
- 内核级线程: 线程管理的全部工作由OS内核来做,内核专门提供了一个KLT(Kernel Level
Threads)应用程序设计接口(API)供开发者使用。例如Windows 2000/XP。 - 用户级线程: 线程管理的全部工作由应用程序来做,在用户空间内实现,内核是不知道线程的存在的。线程库是线程运行的支撑环境。
- 混合式线程(例如Solaris)