操作系统笔记:第二章—进程的描述与控制

2.1进程的基本概念

要点

1.分析程序执行顺序、以及并发的特征

2.进程的概念、特征与状态

3.进程控制块及其组织

1)引入前趋图

描述进程执行前后关系的图

有向无循环图(DAG)

Pi结点:描述一个程序段、进程、或一条语句。

有向边“->”:结点之间的偏序或前序关系

Pi->Pk,则Pi是Pk的直接前趋,Pk是Pi的直接后继。

2)程序顺序执行时的特征

(1)顺序性  处理机的操作严格按程序规定顺序执行

(2)封闭性 程序一旦开始执行,其计算结果不受外界因素影响。

(3)可再现性 程序执行只要初始条件一样,不论如何停顿,重复执行多少次结果都一样。

多个程序如果无序并发,得到的只能是混乱的执行结果,

多道程序运行,走走停停的可能顺序有很多种,符合前趋图的关系才是合理并发。

4)间断性(运行表现)

    多道->程序并发执行->要共享系统的资源 ->形成相互制约的关系->  相互制约导致并发程序具有“执行—暂停—执行”这种间断性的活动规律。

进程的定义:

OS利用“进程实体”控制程序执行就产生了“进程”。

进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。

①结构性特征,进程的根本——PCB

②动态性   进程实质上是进程实体的一次有生命期的执行过程。程序只是静态的一组有序指令。

③并发性  多个进程实体同存于内存中,在一段时间内同时运行。有PCB的程序才能并发。

④独立性

⑤异步性

补充:区别进程与程序

1)动与静:

进程是动态的,程序是静态的:程序是有序代码的集合;进程是程序的执行。

2)永久与暂时:

进程是暂时的,程序是永久的:进程是一个状态变化的过程,程序可长久保存。

3)结构:

l进程的组成包括程序、数据和进程控制块(进程各种控制信息)。

4)进程与程序的对应关系:

都可1对n。通过多次执行,一个程序可对应多个进程;通过调用关系,一个进程可包括多个程序。

进程的基本状态:

        进程执行时的间断性,决定了其具有多种状态。把握各进程所属的状态对进程控制至关重要。

进程的的三种基本状态:就绪状态,执行状态,阻塞状态。


就绪状态(Ready):进程已经获得了所需的资源,只要得到了CPU就可以立即执行,通常情况下系统中会有多个就绪进程,处在就绪队列。

执行状态(Running):进程已经获得CPU,正处在执行状态。

阻塞状态(Blocked):正在执行的进程由于发生某事而无法继续执行,(请求I/O、申请缓冲、时间片到)便放弃处理机而处于暂停的状态。

各种状态下的进程队列

单处理机系统,执行态的进程只有一个;

就绪态、阻塞态的进程可有多个。一般讲它们分别排称一个队列,称就绪队列、阻塞队列。

阻塞队列有的会根据不同原因再排成多个队列。

三状态转换图:

挂起状态:因某些需要,需要经一些进程挂起而不接受调度。

进程控制块:为了描述和及控制进程的运行,系统为每个进程定义了一个数据结构--进程控制块PCB(Process Control Block)。系统总是通过PCB来对进程进行控制,PCB是

进程存在的唯一标志。

 进程控制块PCB:

分析OS调度某进程的过程

查该进程的PCB,获取其状态、优先级

根据PCB保存的处理机状态信息,恢复现场

根据PCB中程序和数据的内存始址,找到其程序和数据

执行中的同步信号等也要查阅PCB,暂停时进程执行的处理机环境保存回PCB。

进程控制块是进程存在的唯一标志:

进程创建时,PCB建立并伴随进程运行的全过程,直到进程撤消而撤消。PCB就象我们的户口。

进程管理和控制的最重要的数据结构

那么,PCB里面有什么?存放在哪?怎么组织这么多程序的PCB?

PCB中包含的信息:

(1)进程标识符

每个进程都必须有一个唯一的标识符:

内部标示符:唯一的数字序号,方便系统使用

外部标示符:方便用户使用,用户进程访问某进程时使用

(2)处理机状态

主要由处理机的各种寄存器中的内容组成,被中断时这些信息要存放到PCB。

通用寄存器:用户程序访问的,暂存信息

指令计数器:下一条指令地址

程序状态字PSW:一些状态信息

用户栈指针:每个用户进程都有的存放过程和系统调用参数及调用地址的一组系统栈。

(3)进程调度信息

进程状态;

进程优先级;

进程调度所需的其他信息:调度算法相关信息;

事件:状态转换有关的事件;

(4)进程控制信息

程序和数据的地址(单个进程)——数据所在的内外存地址

进程同步和通信机制(多进程间)——同步和通信机制的信号量、消息队列指针等

资源清单

链接指针(PCB的组织)——本PCB所在队列的下一个进程PCB首地址。

2)PCB信息的存放

系统运行中有若干个程序的PCB,它们常驻内存的PCB区。采用的数据结构:PCB结构体,PCB链表或队列。

3)PCB的组织方式

链接方式:

同一状态的PCB,依靠链接指针链接成队列。就绪队列;若干个阻塞队列;空白队列(PCB区的空PCB块)


索引方式:

同状态的PCB同样集中记录,但以索引表的方式记录PCB的地址。用专门的单元记录各索引表的首地址。


2.2进程控制

进程控制一般由OS的内核中的原语(Primitive)实现,原子操作(Action Operation)在执行过程中不允许被中断。

进程控制的基本过程:

进程的创建

进程的终止

进程的阻塞与唤醒

进程的挂起和激活


系统中运行的进程并不都是孤立的,有的进程运行后,会调用其他进程来执行,这样就组成了进程间的父子关系。

1.进程的创建

1)一个进程创建另一进程的事件(原因)

用户登录:分时情况下用户的请求

作业调度:批处理中

提供服务:运行中的用户程序提出功能请求,要创建服务进程(如打印服务)

应用请求:应用程序自己创建进程,完成特定功能的新进程。(木马程序)

2)创建过程

原语是由若干指令构成的原子操作过程,作为整体实现功能,不可被打断。

进程创建的步骤,即操作系统调用原语Create()按下述步骤创建新进程。

(1)申请空白PCB

(2)为进程分配资源

(3)初始化进程控制块

(4)将新进程插入就绪队列

进程的阻塞与唤醒(原语Block(),Wakeup()必须成对使用)

(1)请求系统服务

(2)启动某种操作

(3)新数据尚未到达

(4)无新工作可做

进程的挂起与激活

(1)检查被挂起进程的状态,活动就绪则改为静止就绪,活动阻塞则改为静止阻塞

(2)将该PCB复制到内存(方便检查)/外存(对换)指定区域

(3)若挂起的进程是执行态,则需重新进行进程调度。

关于调度

进程控制中,状态转换和调度密切相关。

运行态进程的改变必然产生调度行为

只要产生新就绪态进程,就需考虑调度策略

只要是采用抢占式调度,要检查新就绪进程是否可抢占CPU,引起新的调度。

2.3进程同步

进程同步的主要任务就是对多个相关进程在执行次序上进行协调,以使并发执行的诸进程之间能够有效的共享资源和相互合作。从而使程序的执行具有可再现性。

进程间的两种制约关系:

间接制约:多出现在同一系统中,如两个进程共享打印机资源。

直接制约:如进程A要给进程B输入数据。

临界资源:如打印机,磁带机等。

人们把每个进程中访问临界资源的那段代码成为临界区,将检查某资源是否被访问的代码成为进入区,访问后将临界区标志恢复为未被访问的代码叫做退出区。

1.进程同步的基本概念

1)进程同步的主要任务:

   使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。

2)临界资源

一次仅允许一个进程使用的资源。

生产者—消费者问题:

一群生产者进程生产产品供给消费者进程消费,在两者之间设置具有n个缓冲区的缓冲池,生产者进程所生产的产品放入一个缓冲区中,消费者进程可从一个缓冲区中取走产品去消费。

生产者和消费者都以异步方式运行,但它们之间必须保持同步:没有产品不能取,没有空间不能放。也不能同时对一个空间进行取和放

生产一个,消费一个,还有的产品数应是5。本例顺序得到结果4,生产方会认为还可以继续生产n-4个。比实际需求的n-5多生产的一个必然会覆盖一个旧产品。若后两句交换顺序得到结果又是6,消费方则会错误的向下多消费一个。

同步与互斥:

互斥:在操作系统中,当一个进程进入临界区使用临界资源时,另一个进程必须等待,直到占用临界资源的进程退出临界区,我们称进程之间的这种相互制约关系为“互斥”。

同步:多个相互合作的进程,在一些关键点上可能需要互相等待或互相交换信息,这种相互制约关系称为进程同步关系。可理解为“有序”。

3)临界区

每个进程中访问临界资源的那段代码叫临界区。为了正确同步,对临界区的代码要增加控制

进入区:对欲访问的临界资源进行检。若此刻未被访问,设正在访问的标志

临界区:访问临界资源的代码。

退出区:将正在访问的标志恢复为未被访问的标志

剩余区:其余部分

4)同步机制应遵循的规则

每个进程中访问临界资源的那段代码叫临界区。为了正确同步,对临界区的代码要增加控制。同步机制应该遵循的规则:

空闲让进,忙则等待,有限等待,让权等待。

信号量机制:

1 整型信号量:

1.信号量定义为一个整型量;

2.根据初始情况赋相应的值;

3.仅能通过两个原子操作来访问。

最初由Dijkstra把整型变量定义为一个用于表资源数目的整型量S,它与一般整型量不同,仅可通过两个标准的原子操作(P、V操作)wait(S)和Signal(S)来访问。

操作描述:

wait(S):while S<=0 do no-op;//如果资源为空,则循环等待

S:=S-1;//一旦有资源则使用资源,资源数目减一

signal(S): S:=S+1;//生产资源。

2 记录型信号量:

该机制中除了一个表示资源数目的变量Value之外,还增加了一个进程链表L,用于链接上述所有等待的进程

该记录型的数据结构表示为:

type semaphore = record

value:integer;

L:list of process

end

则wait(S)和Signal(S)操作可描述为:

procedure wait(S)//请求资源

var S:semaphore;//声明一个数据结构

begin

S.value = S.value - 1;//请求一个单位资源,S.value的绝对值表示已阻塞的进程数目。

if S.value < 0 then block(S.L);//如果该资源已分配完毕,则让其阻塞,放弃处理机,并插入到信号量链表

end

procedure signal(S)//释放资源

var S: semaphore;

begin

S.value = S.value + 1;//释放一个单位资源,若释放后S.value仍然是负值则说明仍有进程在等待,则唤醒S.L链表中的第一个等待进程

if S.value <= 0 then wakeup(S.L);

end

若S.value初值为1,则信号量转为互斥信号量,只允许一个进程访问临界资源。

民航售票系统问题

n个售票处。每个售票处通过终端访问系统的公用数据区

假定公用数据区中分别用Ri表示某时间i次航班的现存票数。

Pi表示某售票处的处理进程,试用信号量实现进程间的互斥关系。

Var  s: semaphore :=1;

       begin

        parbegin

            process Pi:

begin

repeat

P(s);

按旅客定票要求找到Ri

IF

Ri >=1

then

    Ri =Ri -1;

  输出一张票;

End

if

V(s);

输出“票已售完”;

until

false;

  end

             parend

      end

3 AND型信号量

上述各进程问题针对进程之间共享一个临界资源而言。但有些时候一个进程需要获得两三个资源方可执行。设进程A,B都要求访问数据D和E。则为这两个临界资源分别设置互斥的信号量Dmutex,Emutex = 1;则在两个进程中都需要对Dmutex和Emutex进行操作,即

process A: process B:

wait(Dmutex); wait(Emutex);

wait(Emutex); wait(Dmutex);

但这样交替执行四个操作的时候,会发生死锁。故该AND同步机制的基本思想就是将进程所需资源一次性分配给进程,使用完后一起释放。即在wait操作中增加

AND的条件,成为AND同步,或成为同步wait操作,即Swait():

Swait(S1,S2,……,Sn)

if Si >= 1 and …… and Sn >= 1 then

for i:= 1 to n do

Si:= Si - 1;

endfor

else

//等待

endif

Ssignal(S1,S2,……,Sn)

for i:= 1 to n do

Si:= Si + 1;

//唤醒等待进程

endfor

4 信号量集

变量和信号量

buffer: array [ 0, …, n-1] of item;

in, out: integer :=0, 0;

不使用Counter变量,而是用信号量

Var  mutex,empty, full:

semaphore :=1,n, 0;

记录型变量一次只能获得或释放一个单位资源,当一次需要N个单位资源的时候显得低效。因此,当资源数量低于某一下限值时便不予以分配。因此Swait操作可描述如下

,S为信号量,d为需求值,t为下限值。Swait可描述为

Swait(S1,t1,d1,...,Sn,tn,dn)

if S1 >= t1 and ... Sn >= tn then

for i:=1 to n do

Si:=Si - di;

endfor

else

//阻塞等待

endif

for i:=1 to n do

Si:=Si + di;

//释放资源

endfor;

Ssignal(S1,t1,d1,...,Sn,tn,dn)

利用信号量实现的前趋关系:

如图

Var a,b,c,d,e,f,g: semaphore:=0,0,0,0,0,0,0;

begin

parbegin

begin S1; signal(a);signal(b);end;

begin wait(a);S2;signal(c);signal(d);end;

begin wait(b);S3;signal(e);end;

begin wait(c);S4;signal(f);end;

begin wait(d);S5;signal(g);end;

begin wait(e);wait(f);wait(g);S6;end;

parend

end

管程机制

管程是由代表共享资源的数据结构,以及由对该共享数据结构实施操作的一组过程所组成的资源管理程序,共同构成的一个操作系统的资源管理模块。

管程由四部分组成:

1 管程的名称

2 局部于管程内部的数据结说明

3 对数据结构进行操作的一组过程

4 对局部于管程内部的共享资源设置初始化值的语句

条件变量:管程中对每个条件变量都须予以说明:

Var x,y:conditon

x.wait;//正在调用管程的进程因x条件的需要被阻塞或挂起。调用x.wait将自己插入到x条件的等待队列上,并释放管程,直到x条件变化。

x.signal;//正在调用管程的进程发现x条件发生变化,则调用x.signal,重新启动一个因x条件而阻塞或挂起的进程

管程(monitor)机制

1.管程的组成

2.管程的特点

3.管程的同步控制(条件变量)

类比生产者—消费者问题

需要封装什么?

1.多进程需访问的变量:

§buffer,in,out;

§empty,full;

2.对变量做的操作:

§向buffer放/取产品,移动指针in,out;

§控制放或取的信号量操作wait、signal;

管程的组成:

1.一组局部变量

2.对局部变量操作的一组过程

3.对局部变量进行初始化的语句。(联想面向对象中的类)

管程特点

任何进程只能通过调用管程提供的过程入口才能进入管程访问共享数据;

就如同使用临界资源,就要先通过其信号量的申请。

任何时刻,仅允许一个进程在管程中执行某个内部过程。

如何实现同步?

对共享变量互斥操作:

  管程的特点直接实现了该要求,进程一次一个进入管程调用内部过程操作共享变量。

管程的互斥访问完全由编译程序在编译时自动添上,无须程序员关心,能保证正确。

操作的同步控制:

靠条件变量的操作管理实现。

  进入管程但不能获取资源操作的过程将阻塞,并在满足条件时被唤醒执行。

条件变量

(主要作用就是进程同步的阻塞和唤醒控制)

局部于管程的变量有两种:

普通变量

条件变量(用于控制进程阻塞和唤醒)

类似信号量变量,但不取具体值;相当于每个阻塞队列的队列指针。

对条件变量的操作需结合对普通变量的条件判断,从而控制进程状态。

管程的优点

保证进程互斥地访问共享变量,并方便地阻塞和唤醒进程。管程可以以函数库的形式实现。相比之下,管程比信号量好控制。

管程可增强模块的独立性:系统按资源管理的观点分解成若干模块,用数据表示抽象系统资源,使同步操作相对集中,从而增加了模块的相对独立性

引入管程可提高代码的可读性,便于修改和维护,正确性易于保证:采用集中式同步机制。一个操作系统或并发程序由若干个这样的模块所构成,一个模块通常较短,模块之间关系清晰。

管程的缺点

大多数常用的编程语言中没有实现管程,如果某种语言本身不支持管程,那么加入管程是很困难的。

虽然大多数编程语言也没有实现信号量,但可将P、V操作作为一个独立的子例程或操作系统的管理程序调用加入。

进程通信

  进程通信是指进程之间的信息交换。

一、低级通信——进程之间的互斥和同步

  信号量机制是有效的同步工具,但作为通信工具缺点如下:

(1)效率低(通信量少)

(2)通信对用户不透明(程序员实现,操作系统只提供共享存储器供代码操作)

二、高级进程通信

  用户直接利用操作系统提供的一组通信命令,高效地传送大量数据的通信方式。

  操作系统隐藏了进程通信的细节,对用户透明,减少了通信程序编制上的复杂性。

1.进程通信的类型

高级通信机制可归结为四大类

①共享存储器系统(操作存储区方式)

  相互通信的进程共享某些数据结构或共享存储区,进程之间能够通过这些空间进行通信。

a.基于共享数据结构的通信方式(低级)

b.基于共享存储区的通信方式(高级)

②消息传递系统(发--收方式)

最广泛使用的一种,进程间的数据交换,以格式化的消息为单位。屏蔽底层复杂操作。

单机:操作系统底层编程中的消息传递系统调用;

计算机网络:消息称为报文。程序员直接利用系统提供的一组通信命令(原语)进行通信。(④客户机-服务器系统)

③管道通信(中间文件方式)

所谓“管道”,是指用于连接一读进程和一写进程以实现通信的一个共享文件,又名pipe文件。

向共享文件输入的写进程以字符流形式将大量的数据送入管道;而接收管道输出的读进程则从管道中接收(读)数据。

首创于UNIX系统。其管道机制需提供三方面的协调能力:互斥、同步、确定对方是否存在。

④Client-Server system

套接字(Socket)

一个套接字就是一个通信标识类型的数据结构,包含了通信目的的地址,端口号,传输层协议、进程所在的网络地址,以及针对C\S程序提供的不同系统调用(API函数)等。

系统中所有的连接都持有唯一的一对套接字及端口连接,从而方便地区分来自不同应用程序进程或网络连接的通信,确保通信双方间逻辑链路的唯一性。

远程过程调用(远程方法调用)

RPC 有很多正面的应用,比如网络文件系统NFS、Web

Service等,也是网络安全中容易被攻击的技术。

Remote Procedure Call,远程过程调用。也就是说,调用过程代码并不是在调用者本地运行,而是要实现调用者与被调用者二地之间的连接与通信。

RPC的基本通信模型是基于Client/Server进程间相互通信模型的一种同步通信形式;它对Client提供了远程服务的过程抽象,其底层消息传递操作对Client是透明的。

2.消息传递通信的实现方法

1)直接通信方式

  发送进程利用OS所提供的发送命令(原语),直接把消息发送给目标进程。此时,发送进程和接收进程都以显式方式提供对方的标识符。通常利用系统通信命令(原语):

2)间接通信方式

  基于共享数据结构的实体用来暂存发送给目标进程的消息;接收进程则从该实体中,取出对方发送给自己的消息。通常把这种实体称为信箱。

消息在信箱中可以安全地保存,只允许核准的目标用户随时读取。既可实时通信,又可非实时通信。

3.消息传递系统的实现

  单机和网络环境下的高级进程通信广泛采用“消息传递”方式,需要考虑的问题:

①通信链路的建立

计算机网络环境下,用原语显式建立/拆除链路

单机系统只须利用系统原语,进程间链路由系统自动管理。

②消息格式

单机系统,发送与接收进程在同一台机器,环境相同故格式简单;

网络环境下,受不同目标机器的环境和长距离信息传输等因素的影响,消息格式较复杂,消息常是“大头+正文”

③同步方式

即考虑平时闲着,还是平时忙碌?

发送进程阻塞、接收进程阻塞(无缓冲紧密同步)发送进程不阻塞、接收进程阻塞(服务器程序)发送进程和接收进程均不阻塞(缓冲队列)

4.消息缓冲队列通信机制

①不需管理链路

②定义简单数据结构(亦即消息格式)

本机通信消息结构简单,如下:

type message

buffer = record

  sender;   发送者进程标识符

  size;   消息长度

  text;   消息正文

  next;   指向下一消息缓冲区的指针

end

③实现发送和接收的操作原语

procedure send(receiver, a)

   begin

        getbuf(a.size, i); 根据a.size申请缓冲区

        i.sender :=a.sender;  将发送区a中的信息复制到 i

        i.size :=a.size;

        i.text :=a.text;

        i.next :=0;

获取接收进程内部标识符

      getid(PCB set, receiver, j);

     insert(j.mq,i); 将消息缓冲区插入目标消息队列

   end

线程

1、认识线程

多线程系统中,同一个进程中的多个线程

共享进程资源

可并发执行

2.线程的属性

  多线程OS中,一个进程包括多个线程,每个线程都是利用CPU的基本单位。

轻型实体:只需一点必不可少的、能保证独立运行的资源。(TCB)

独立调度和分派的基本单位:调度切换迅速且开销小。可并发执行

共享进程资源:同进程中的线程可共享相同的进程地址空间、已打开文件、信号量机构等。

3.线程的信息

状态参数   标识符、运行状态、优先级、寄存器状态、堆栈、专有存储器、信号屏蔽等。

运行状态   执行、就绪、阻塞

多线程编程过程是类似的:

可用win32

API编写C风格程序

C的main既是规定了主线程的代码。启动程序时,系统根据main地址,启动主线程。

在主线程代码某处利用线程创建函数即可创建线程;给创建函数编写线程功能代码;

利用其他一系列函数使系统管理多个线程。

也可用封装好的类库,如JAVA,MFC

4.

线程的创建和终止

  在多线程OS中,应用程序启动时,通常只有一个线程(初始化线程)在执行,它根据需要再创建若干线程。

创建新线程

  利用线程创建函数(或系统调用),提供相应参数。线程创建函数执行完后,返回一个线程标识符供以后使用。

线程被终止:

  不立即释放资源,只有当进程中的其它线程执行分离函数后,资源才分离出来能被其它线程利用。

  被终止而未释放资源的线程仍可被需要它的线程调用,使其重新恢复运行。

5.多线程系统中的进程

进程只是用于分配系统资源

包括多个线程

不是执行实体,线程在进程范围内作为执行实体。

6.线程的管理

同步和通信机制

1)互斥锁

比较简单的,控制线程互斥访问资源;

适用于高频度使用的关键共享数据和程序段;

unlock和lock两个锁操作原语;

2)条件变量

与互斥锁一起使用

锁保证互斥进入临界区,但利用条件变量使线程阻塞

注意不满足条件时,wait条件变量:

释放互斥锁

进程阻塞在条件变量指向队列中

被唤醒后要重新再设互斥锁

3)信号量

私用信号量(privatesamephore)

用于同进程的线程间同步,数据结构存放在应用程序的地址空间。属于特定进程,OS感知不到其存在。

公用信号量(publicsamephore)

用于不同进程间或不同进程中线程的同步,数据结构由OS管理,存放在受保护的系统存储区。

二、线程的实现方式

1.内核线程KST(kernel-level thread)

依赖于内核,利用系统调用由OS内核在内核空间完成创建、撤消、切换等线程工作。

时间片分配给线程,所以多线程的进程获得更多CPU时间。

2.用户线程ULT(user-level thread)

无须利用系统调用,不依赖于OS核心。进程利用线程库函数创建、同步、调度和管理控制用户线程。

调度由应用软件内部进行,通常采用非抢先式和更简单的规则,也无需用户态/核心态切换,速度比kst快。

3.组合方式

内核支持多KST线程的管理,同时也允许用户应用程序级的线程管理。

你可能感兴趣的:(操作系统笔记:第二章—进程的描述与控制)