第三章进程管理.docx
《第三章进程管理.docx》由会员分享,可在线阅读,更多相关《第三章进程管理.docx(41页珍藏版)》请在冰豆网上搜索。
第三章进程管理
第三章进程管理
3.1知识点汇总
1、程序顺序执行与并发执行比较(见表3-1)
表3-1
顺序执行
并发执行
程序顺序执行
间断执行,多个程序各自在“走走停停”种进行
程序具有封闭性
程序失去封闭性
独享资源
共享资源
具有可在现性
失去可再现性
有直接和简接的相互制约
2、多道程序设计概念及其优点
1)多道程序设计:
是在一台计算机上同时运行两个或更多个程序。
2)多道程序设计的特点:
多个程序共享系统资源、多个程序并发执行
3)多道程序设计的优点:
提高资源利用率、增加系统吞吐量
并发技术的实现及其带来的问题
1)如何解决现场信息的保存和恢复
2)CPU的调度问题
3)进程间的层次关系
4)进程间的同步互斥问题
5)进程安全问题
3、什么是进程,进程与程序的区别和关系
(1)进程的引入
由于多道程序的特点,程序具有了并行、制约和动态的特征,就使得原来程序的概念已难以刻划和反映系统中的情况了。
(2)进程:
程序在并发环境下的执行过程。
进程的定义:
是一个程序的一次动态执行,或者说是一个正在执行中的程序。
(3)进程与程序的主要区别:
程序是永存的,进程是暂时的
程序是静态的观念,进程是动态的观念
进程由三部分组成:
程序+数据+进程控制块(描述进程活动情况的数据结构)
进程和程序不是一一对应的
一个程序可对应多个进程即多个进程可执行同一程序
一个进程可以执行一个或几个程序
进程特征:
动态性、并发性、调度性、异步性、结构性
4、进程的基本状态及其转换
(1)、进程三态转换分析
运行态:
进程正在使用CPU。
等待态(阻塞态):
进程正在等待I/O完成(或其他事件发生),不在使用CPU,也不能使用CPU。
进程进入等待队列中。
就绪态:
进程不在使用CPU,但已准备好使用CPU(不再等待I/O或其他事件)。
进程进入就绪队列中。
图3-2进程三种基本状态见相互转换
三态转换示意图
状态转换原因:
就绪态进入运行态
进程被调度程序选中
运行态进入就绪态
例如:
时间片到
运行态进入等待态
例如:
等I/O完成
等待态进入就绪态
例如:
I/O结束
从其他状态进入就绪态的进程需要置入调度队列(就绪队列),等待调度。
根据CPU的调度策略决定就绪队列中的哪个进程先使用CPU进入运行态。
3-3进程七态转换示意图
5、进程是由哪些部分组成,进程控制块的作用
(1)进程的组成:
由程序、数据集合和PCB三部分组成。
(2)进程控制块的作用:
进程控制块是进程组成中最关键的部分。
1)每个进程有唯一的PCB。
2)操作系统根据PCB对进程实施控制和管理。
3)进程的动态、并发等特征是利用PCB表现出来的。
4)PCB是进程存在的唯一标志。
(3)、建立进程的过程
1)创建一个PCB
赋予一个统一进程标识符
2)为进程映象分配空间
3)初始化进程控制块
许多默认值(如:
状态为New,无I/O设备或文件...)
4)设置相应的链接
如:
把新进程加到就绪队列的链表中
进程控制块表(PCB表)每个系统一张进程控制块表。
PCB表的长度是有限的。
每个进程的在表中占一行。
每个进程所占的那一行,就是该进程的进程控制块(PCB)。
PCB中的内容:
进程号、进程状态、进程调度优先级、现场信息、就绪队列指针、等待队列针、叶标或界址寄存器、打开文件表、记账信息,等。
6、PCB组织方式
线性队列、链接表、索引表
PCB表的组织方式有链表和索引两种
链表式的PCB表
图3-4索引式的PCB表
7、进程空间结构
(1)程序的文件结构。
可执行目标程序存放在外存中。
由三部分组成:
代码、静态初始化数据、头,包括外部连接数据,参数,日期,厂商,长度等,头的具体内容和格式由具体操作系统确定。
(2)进程空间结构。
指进程在内存的所有代码、数据栈、以及有关信息的组合和总称。
一个进程的内存空间而言,可以在逻辑上分成3个部份:
代码区,静态数据区和动态数据区。
动态数据区一般就是“堆栈”。
“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。
代码区:
存放程序的二进制代码。
由操作系统分配释放。
静态数据区:
存放全局变量和静态变量。
初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
由操作系统分配释放。
栈:
存放函数的参数值,局部变量等。
由操作系统分配释放。
栈是指可供程序使用的一部分动态内存空间,但是分配与释放顺序都是特定。
栈是后进先出的。
这就是说,你最近分配的那个存储对象将是第一个被删除的。
堆:
可由程序动态申请的内存空间。
由程序在运行时动态地分配,使用完可由程序释放,或进程结束后由操作系统来释放。
如:
用malloc方法申请的内存空间,还有New方法产生的数据的空间,都在这里分配。
堆是指可供程序使用的一部分内存空间,也称为动态内存区域。
在堆中,存储空间分配与释放的次序是没有限制的。
这就是说,假设你顺序分配了三块空间,以后你可以按任何顺序去把它们销毁。
堆管理器会替你管理一切。
//main.cpp
inta=0;静态数据区中的全局初始化区
char*p1;静态数据区中的全局未初始化区
main()
{
intb;栈
chars[]="abc";栈
char*p2;栈
char*p3="123456";123456在常量区,p3在栈上。
staticintc=0;全局(静态)初始化区
p1=(char*)malloc(10);
p2=(char*)malloc(20);//分配得来得10和20字节的区域就在堆区。
strcpy(p1,"123456");
//123456放在常量区。
}
实际上用户进程中有两个栈,一个用户态栈(在用户区),一个系统态栈(在系统区)。
8、进程的同步与互斥
(1)同步:
是进程间共同完成一项任务时直接发生相互作用的关系。
(2)互斥:
排它性访问即竞争同一个物理资源而相互制约。
9、什么是临界资源、临界区?
(1)临界资源:
一次仅允许一个进程使用的资源。
(2)临界区:
在每个进程中访问临界资源的那段程序。
(3)互斥进入临界区的准则:
如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
任何时候,处于临界区内的进程不可多于一个。
如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
10、信号量
(1)信号量定义:
信号量(信号灯)=<信号量的值,指向PCB的指针>
(2)信号量的物理意义:
信号量的值大于0:
表示当前资源可用数量
小于0:
其绝对值表示等待使用该资源的进程个数
信号量初值为非负的整数变量,代表资源数。
信号量值可变,但仅能由P、V操作来改变。
11、P/V操作原语
(1)P操作原语P(S)
P操作一次,S值减1,即S=S-1(请求分配一资源);
如果S≥0,则该进程继续执行;如果S<0表示无资源,则该进程的状态置为阻塞态,把相应的PCB连入该信号量队列的末尾,并放弃处理机,进行等待(直至另一个进程执行V(S)操作)。
(2)V操作原语(荷兰语的等待)V(S)
V操作一次,S值加1,即S=S+1(释放一单位量资源);
如果S>0,表示有资源,则该进程继续执行; 如果S≤0,则释放信号量队列上的第一个PCB所对应的进程(阻塞态改为就绪态),执行V操作的进程继续执行。
12、进程间简单同步与互斥的实现
(1)用P,V原语实现互斥的一般模型
设互斥信号量mutex初值为1
(2)用P、V原语操作实现简单同步的例子
S1缓冲区是否空(0表示不空,1表示空),初值S1=0;
S2缓冲区是否满(0表示不满,1表示满),初值S2=0;
(3)生产者——消费者问题(OS典型例子):
mutex互斥信号量,初值为1;full满缓冲区数,初值为0;empty空缓冲区数,初值为N;
13、线程模型
(1)线程的概念、作用和基本原理
为了解决“基于同数据区的同时多请求”提出了线程模型。
线程是基于进程的一个运行单位,即线程是隶属于进程的,比进程更小的一个运行单位,一个进程可以有一个或多个线程。
这些现成共享这个进程的地址空间(代码,数据)及大部分管理信息,但每个线程有自己的程序计数器值,栈,现场及少量的管理信息。
采用线程模型,减少并发执行时的时空开销,进程的创建、撤消、切换较费时空,因它既是调度单位,又是资源拥有者。
线程是系统独立调度和分派的基本单位,其基本上不拥有系统资源,只有少量资源(IP,寄存器,栈),但共享其所属进程所拥有的全部资源。
线程的状态:
运行,阻塞,就绪,终止。
3.2例题解析
例3.2.1试说明进程和程序之间的区别和联系。
解进程和程序是既有区别又有联系的两个概念。
(1)进程是动态的,程序是静态的。
程序是一组有序的指令集合,是一个静态的概念;进程则是程序及其数据在计算机上的一次执行,是一个动态的集合。
离开了程序,进程就失去了存在的意义,但同一程序在计算机上的每次运行将构成不同的进程。
程序可看作是电影的胶片,进程可以看作电影院放电影的过程。
(2)一个进程可以执行多个程序,如同一个电影院的一场电影可放映多部影片。
(3)一个程序可被多个进程执行,如同多个影院同时利用一个电影的胶片放映同一部电影。
(4)程序可以长期保存,进程只能存在于一段时间。
程序是永久存在的,而进程有从被创建到消亡的生命周期。
例3.2.2举例说明多道程序系统失去了封闭性和再现性。
解例如,有两个循环程序A和B,共享一个变量N。
程序A每执行一次时,都要做N:
=N+1操作;程序B则每执行一次时,都要执行print(N)操作,然后再将N的值置成“0”。
程序A和B在多道程序系统中同时运行。
假定某时刻变量N的值为n,可能出现下述三种情况:
(1)N:
=N+1在print(N)和N:
=0之前,此时得到N值变化过程为n+1、n+1、0;
(2)N:
=N+1在print(N)和N:
=0之后,此时得到N值变化过程为n、0、1;
(3)N:
=N+1在print(N)之后和N:
=0之前,此时得到N值变化过程为n、n+1、0。
所以,在A、B程序多次执行过程中,虽然其每次执行时的环境和初始条件都相同,但每次得到的结果却不一定相同。
例3.2.3为什么将进程划分成执行、就绪和阻塞三个基本状态?
解根据多道程序执行的特点,进程的运行是走走停停的。
因此进程的初级状态应该是执行和等待状态。
处于执行状态的进程占用处理机执行程序,处于等待状态的进程正在等待处理机或者等待其它某种事件的发生。
但是,当处理机空闲时,并不是所有处于等待状态的进程都能放到处理机上执行,有的进程即使分配给它处理机,它也不能执行,因为它的执行的条件没有得到满足。
因此,将等待状态的进程分成两部分,一部分是放在处理机上就能立即执行,这就是就绪的进程;另一部分是仍需等某种事件发生的进程,即使放在处理机上也不能执行的进程,这就是阻塞进程。
例3.2.4进程的挂起状态与进程的阻塞状态和就绪状态有何异同?
解相同点是它们都没有占用处理机。
不同点是挂起状态的进程是处于一种静止状态,不会参与对资源的竞争,在解除挂起之前,进程不会有新的资源要求,也不会有占用处理机的机会;阻塞状态和就绪状态的进程均处于活动状态,它们都有获得处理机的机会,都可能有新的资源要求。
例3.2.5两个并发进程P1和P2的程序代码在下面给出。
其中,A、B、C、D和E均为原语。
P1:
beginP2:
begin
A;D;
B;E;
C;end
end
请给出P1、P2两个进程的所有可能执行的过程。
解P1和P2进程以不可预知的速度推进,它们所有可能的执行过程为:
(1)A→B→C→D→E
(2)A→B→D→E→C
(3)A→B→D→C→E(4)A→D→B→E→C
(5)A→D→B→C→E(6)A→D→E→B→C
(7)D→E→A→B→C(8)D→A→B→C→E
(9)D→A→B→E→C(10)D→A→E→B→C
例3.2.6在操作系统中为什么要引入进程这一概念?
解在单道程序设计环境下,CPU被一道程序独占,CPU严格按该程序的指令顺序来执行。
单道程序具有顺序性、封闭性和可再现性。
单道程序有许多局限性,于是出现了多道程序。
在多道程序环境中,有若干个程序同时运行,具有了许多新的特征,如并发性、动态性以及相互制约性等。
这时,程序的概念已经不能描述上述这些特征,并发程序的特征必须用新的概念来描述,于是引进了“进程”的概念。
例3.2.7在多道程序系统,当进程需要等待某种事件发生时,进程将进入何种状态?
解当进程需要等待某种事件发生时,进程进入何种状态取决于进程程序的处理方式。
进程可以调用阻塞原语,将自己阻塞,暂时放弃处理机;进程也可以采用不放弃处理机的循环等待的方式等待某种事件发生。
因此,当进程需要等待某种事件发生时,进程并不是一定要进入阻塞状态。
例3.2.8父进程创立子进程与主程序调用子程序有何不同?
解父进程创立子进程后,父进程与子进程同时执行;主程序调用子程序,主程序暂停在调用点,子程序开始执行,直到子程序执行完毕返回,主程序开始执行。
例3.2.9进程控制块PCB的作用是什么?
它主要包含哪些内容?
解操作系统管理的进程是多种多样的,要对这些进程实施有效的管理,必须对进程进行抽象。
为了便于系统控制和描述进程的活动,在操作系统核心为进程定义了一个进程控制块PCB。
PCB用于描述进程的基本情况以及进程运行和变化的过程,它与进程一一对应。
当系统创建进程时,为进程分配一个PCB;在进程运行过程中,系统通过PCB对进程实施管理和控制;进程结束时,系统将收回PCB。
PCB中的内容主要包括调度信息和现场信息两大部分。
调度信息包括进程名、进程号、优先级、当前状态、资源信息、程序和数据的位置信息、隶属关系和各种队列指针信息等。
现场信息主要包括程序状态字、时钟寄存器和界限寄存器等描述进程运行情况的信息。
例3.2.10一个新创建的进程,第一次被调度到CPU上运行时,其“现场”从何而来?
解进程在CPU上交替地执行是通过保存退出进程的现场和恢复新选中进程的现场实现的;而一个进程的“现场”是其上次从CPU上退出时获得的。
但是,一个新创建的、尚未在CPU上运行过的进程还没有“上一次”,那么它的“现场”从何而来?
是从其父进程继承而来,是在进程创建程序执行时,将父进程特意为子进程准备的“现场”复制给子进程。
新创建的子进程就是以此“现场”实施其第一次运行的。
例3.2.11用户级线程和内核支持线程有何区别?
解两者的区别是:
(1)内核支持线程是OS内核可感知的,而用户级线程是OS内核不可感知的。
(2)用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言(如Java)这一级处理的;而内核支持线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。
(3)用户级线程执行系统调用指令时将导致其所属进程被中断,而内核支持线程执行系统调用指令时,只导致该线程被中断。
(4)在只有用户级线程的系统内,CPU调度还是以进程为单位,处于运行状态的进程中的多个线程,由用户程序控制线程的轮换运行;在有内核支持线程的系统内,CPU调度则以线程为单位,由OS的线程调度程序负责线程的调度。
(5)用户级线程的程序实体是运行在用户态下的程序,而内核支持线程的程序实体则是可以运行在任何状态下的程序。
例3.2.12说明SolarisOS的用户级线程、内核线程和轻型进程之间的关系。
解首先要说明的是,这里所说的“内核线程”与“内核支持线程”是有区别的,即“内核线程”是与OS内核中的程序相对应的线程;而“内核支持线程”是指其创建、撤消和切换都需要内核程序支持才能实现的线程,其线程本身所对应的程序可以是OS的内核程序,也可以是内核外运行在用户态的程序,但主要是用户的应用程序。
在SolarisOS中,为了实现“用户级线程”与内核的无关性,在“用户级线程”和“内核线程”之间设立了称之为“轻型进程”(LWP:
Light-WeightProcess)的运行实体,作为两类线程的接口,用户级线程只能通过LWP请求内核线程的支持和服务。
这样做的目的是要将两类线程隔离开来,使系统的运行层次更加清晰,效率和安全性更好。
例3.2.13简述创建进程的大致过程。
解创建一个进程大体分以下几步:
(1)申请一个空白的PCB和唯一的进程标识号pid
(2)为新进程分配除CPU以外的资源,包括内存空间;
(3)初始化PCB中的数据项,包括标志信息、状态信息、控制信息等;
(4)将新进程的PCB插入系统的就绪队列。
例3.2.14多道程序系统程序的执行失去了封闭性和再现性,因此多道程序的执行不需要这些特性,这种说法是否正确?
解这种说法不正确。
可以想象,如果一个程序在多道程序系统中,在相同的输入的情况下,多次执行所得结果是不同的,有谁还敢使用这个程序?
因此,多道程序的执行也需要封闭性和再现性,只不过单道程序系统的封闭性和再现性是先天固有的,多道程序系统的程序执行要想获得封闭性和再现性,需通过程序员的精心设计才能得到。
所使用的方法就是同步和互斥的方法。
例3.2.15多个进程对信号量S进行了5次P操作,2次V操作后,现在信号量的值是-3,与信号量S相关的处于阻塞状态的进程有几个?
信号量的初值是多少?
解
(1)因为S的当前值是-3,因此因为S处于阻塞状态的进程有3个;
(2)因为每进行一次P(S)操作,S的值都减1,每执行1次V操作S的值加1,故信号量的初值为-3+5-2=0;
例3.2.16如下锁的实现方法存在什么缺点?
如何改进?
LOCK(X)UNLOCK(X)
{{
dowhileX=1;X=0;
X=1
}}
解存在的缺点是:
当锁是关闭时,采用的是循环等待的方法,这样的等待还是要占用处理机的时间,应该采用阻塞等待的方法。
改进的锁实现如下:
LOCK(X)UNLOCK(X)
{{
ifX.value=1ifnotempty(X.L)
{insert(*,X.L);{P=remove(X.L);
Block(*)Wakeup(P)
}}
elseX.Value=1elseX.Value=0
}}
这里X.value是锁的值,X.L是存放由于锁X而阻塞的进程的队列。
insert(*,X.L)将当前进程的进程号插入到X.L,remove(X.L)是从X.L中移出一个进程号。
例3.2.17使用多个进程计算Y=F1(X)+F2(X).
解
(1)确定并发和顺序操作
在这个问题中,F1(X)和F2(X)的计算是可以并行处理的,因此F1(X)和F2(X)可以分别出现在两个进程中。
(2)确定互斥或同步的规则
在F1(X)+F2(X)中,必须在F1(X)和F2(X)计算完毕,才能进行加法运算,因此本问题是同步问题。
(3)同步的操作流程
〈进程main〉
创立进程p1来计算F1(X);
创立进程p2来计算F2(X);
F1(X)计算是否完成?
没有,等待;
F2(X)计算是否完成?
没有,等待;②
进行加法运算。
〈进程p1〉
y1=F1(X);
设置F1(X)计算完成标志;③
〈进程p2〉
y1=F2(X);
设置F2(X)计算完成标志。
④
(4)确定信号量的个数和含义
根据同步规则以及操作流程确定信号量的个数是2个,S1和S2:
S1含义是F1(X)计算是否完成;
S2含义是F2(X)计算是否完成。
(5)确定信号量的初值
S1=0;
S2=0。
(6)确定P、V操作的位置
上面①处是一个P操作,P(S1);
上面②处是一个P操作,P(S2);
上面③处是一个V操作,V(S1);
上面④处是一个V操作,V(S2)。
解法1
Main()
Publicy,y1,y2,.P1,P2
SemaphoreS1,S2
{
S1=0;
S2=0;
P1=Creat(N-F1,F1,x,……);
P2=Creat(N-F2,F2,x,……);
P(S1);
P(S2);
y=y1+y2;
}
ProcedureF1(x)
{
y1=计算1;
V(S1);
}
ProcedureF2(x)
{
y2=计算2;
V(S2)
}
解法2
Main()
Publicy,y1,y2,.P1,x
SemaphoreS1
{input(x);
S1=0;
P1=Creat(N-F1,F1,x,……);
Y2=F2(x);
P(S1);
y=y1+y2;
}
ProcedureF1(x)
{
y1=计算1;
V(S1)
}
采用2个进程和1个信号量来实现Y=F1(X)+F2(X)的时候,采用的方法是父进程创立子进程,F1(X)在子进程中计算,F2(X)在父进程中计算,因此F1(X)和F2(X)计算仍然是并发进行的。
S1信号量的含义为F1(X)是否完成。
改进的方法比原来的方法节约一个进程和一个信号量,但并发操作的程度并没有降低。
例3.2.18生产者—消费者问题演变。
情况1一个buffer,一个生产者,一个消费者,生产者只生产一个东西,消费者只进行一次消费,即:
生产者只进行一次putdata操作,消费者只进行一次getdata操作。
解这是一个同步问题,生产者和消费者分别是2个并发的进程。
(1)操作规则
如果buffer为空,则消费者只能等待。
(2)操作流程
<生产者>
{
putdata;
设置Buffer有数据标志V(S)
}
<消费者>
{
判断buffer是否有产品,没有则等待;
getdata;
}
(3)信号量
设置1个信号量full,full表示buffer是否有数据,初值为0。
(4)P、V操作实现
varfull:
semaphore:
=0;
buffer:
array[1]ofitem;
begin
parbegin
producer:
begin
putdata;
V(full);
end
consumer:
begin
P(full);
getdata;
end
parend
end
情况2一个buffer,一个生产者,一个消费者,生产者不断地进行putdata操作,消费者不断地进行getdata操作,即:
生产者不断地生产,消费者不断地消费
(1)操作规则
只有buffer为空时才能进行putdata操作;只有buffer有数据时才能进行putdata操作。
(2)操作流程
<生产者>
{
repeat
判断buffer是否为空,不空则等待;
putdata;
设置buffer有数据的标志;
untilfalse
}
<消费者>
{
repeat
判