154.进程的描述与控制

第二章 进程的描述与控制html

2.1  前趋图和程序执行  

在早期未配置OS的系统和单道批处理系统中,程序的执行方式是顺序执行,即在内存中仅装入一道用户程序,由它独占系统中的全部资源,只有在一个用户程序执行完成后,才容许装入另外一个程序并执行。可见,这种方式浪费资源、系统运行效率低等缺点。 程序员

 

2.1.1  前趋图  

  为了能更好地描述程序的顺序和并发执行状况,咱们先介绍用于描述程序执行前后顺序的前趋图。所谓前趋图(Precedence Graph),是指一个有向无循环图,可记为DAG(Directed Acyclic Graph),它用于描述进程之间执行的前后顺序。图中的每一个结点可用来表示一个进程或程序段,乃至一条语句,结点间的有向边则表示两个结点之间存在的偏序(Partial Order)或前趋关系(Precedence Relation)。算法

  进程(或程序)之间的前趋关系可用“→”来表示,若是进程Pi和Pj存在着前趋关系,可表示为(Pi,Pj)∈→,也可写成Pi→Pj,表示在Pj开始执行以前Pi 必须完成。此时称Pi是Pj的直接前趋,而称Pj是Pi的直接后继。在前趋图中,把没有前趋的结点称为初始结点(Initial Node),把没有后继的结点称为终止结点(Final Node)。此外,每一个结点还具备一个重量(Weight),用于表示该结点所含有的程序量或程序的执行 时间。 数据库

  在图2-1(a)所示的前趋图中,存在着以下前趋关系:   P1→P2,P1→P3,P1→P4,P2→P5,P3→P5,P4→P6,P4→P7,P5→P8,P6→P8,P7→P9,P8→P9 或表示为:  P={P1, P2, P3, P4, P5, P6, P7, P8, P9}    ={(P1, P2), (P1, P3), (P1, P4), (P2, P5), (P3, P5), (P4, P6), (P4, P7), (P5, P8), (P6, P8), (P7, P9), (P8, P9)}编程

  应当注意,前趋图中是不容许有循环的,不然必然会产生不可能实现的前趋关系。如图2-1(b)所示的前趋关系中就存在着循环。它一方面要求在S3开始执行以前,S2必须完成,另外一方面又要求在S2开始执行以前,S3必须完成。显然,这种关系是不可能实现的。         数组

S2→S3,S3→S2安全

 

图2-1 前趋图服务器

 

2.1.2  程序顺序执行 

1. 程序的顺序执行 网络

  一般,一个应用程序由若干个程序段组成,每个程序段完成特定的功能,它们在执行时,都须要按照某种前后次序顺序执行,仅当前一程序段执行完后,才运行后一程序段。例如,在进行计算时,应先运行输入程序,用于输入用户的程序和数据;而后运行计算程序,对所输入的数据进行计算;最后才是运行打印程序,打印计算结果。咱们用结点(Node)表明各程序段的操做(在图2-1中用圆圈表示),其中I表明输入操做,C表明计算操做,P为打印操做,用箭头指示操做的前后次序。数据结构

  这样,上述的三个程序段间就存在着这样的前趋关系:Ii→Ci→Pi,其执行的顺序可用前趋图2-2(a)描述。   即便是一个程序段,也可能存在着执行顺序问题,下面示出了一个包含了三条语句的程序段:

  S1: a :=x+y;   S2: b :=a-5;   S3: c :=b+1;

  其中,语句S2必须在语句S1后(即a被赋值)才能执行,语句S3也只能在b被赋值后才能执行,所以,三条语句存在着这样的前趋关系:S1→S2→S3,应按前趋图2-2(b)所示的顺序执行。

 

图2-2 程序顺序执行的前趋图

 

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

由上所述能够得知,在程序顺序执行时,具备这样三个特征:

① 顺序性:指处理机严格地按照程序所规定的顺序执行,即每一操做必须在下一个操做开始以前结束;

② 封闭性:指程序在封闭的环境下运行,即程序运行时独占全机资源,资源的状态(除初始状态外)只有本程序才能改变它,程序一旦开始执行,其执行结果不受外界因素影响;

③ 可再现性:指只要程序执行时的环境和初始条件相同,当程序重复执行时,不论它是从头至尾不停顿地执行,仍是“停停走走”地执行,均可得到相同的结果。程序顺序执行时的这种特性,为程序员检测和校订程序的错误带来了很大的方便。

 

 2.1.3 程序并发执行  

1. 程序的并发执行 

  咱们经过一个常见的例子来讲明程序的顺序执行和并发执行。在图2-2中的输入程序、计算程序和打印程序三者之间,存在着Ii→Ci→Pi这样的前趋关系,以致对一个做业的输入、计算和打印三个程序段必须顺序执行。但如果对一批做业进行处理时,每道做业的输入、计算和打印程序段的执行状况如图2-3所示。 

 

图2-3 程序并发执行时的前趋图

  由图2-3能够看出,存在前趋关系Ii→Ci,Ii→Ii+1,Ci→Pi,Ci→Ci+1,Pi→Pi+1,而Ii+1和Ci及Pi-1是重叠的,即在Pi-1和Ci以及Ii+1之间,不存在前趋关系,能够并发执行。

  对于具备下述四条语句的程序段:

  S1: a :=x+2   S2: b :=y+4   S3: c :=a+b   S4: d :=c+b   

  可画出图2-4所示的前趋关系。能够看出:S3必须在a和b被赋值后方能执行;S4必须在S3以后执行;但S1和S2则能够并发执行,由于它们彼此互不依赖。

图2-4 四条语句的前趋关系

 

2. 程序并发执行时的特征

  在引入了程序间的并发执行功能后,虽然提升了系统的吞吐量和资源利用率,但因为它们共享系统资源,以及它们为完成同一项任务而相互合做,导致在这些并发执行的程序之间必将造成相互制约的关系,由此会给程序并发执行带来新的特征。

  (1) 间断性。   (2) 失去封闭性。   (3) 不可再现性。

 

2.2  进 程 的 描 述 

2.2.1  进程的定义和特征 

1. 进程的定义

      在多道程序环境下,程序的执行属于并发执行,此时它们将失去其封闭性,并具备间断性,以及其运行结果不可再现性的特征。由此,决定了一般的程序是不能参与并发执行的,不然,程序的运行也就失去了意义。为了能使程序并发执行,而且能够对并发执行的程序加以描述和控制,人们引入了“进程”的概念。

 对于进程的定义,从不一样的角度能够有不一样的定义,其中较典型的定义有:

  (1) 进程是程序的一次执行。

  (2) 进程是一个程序及其数据在处理机上顺序执行时所发生的活动。

  (3) 进程是具备独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。

2. 进程的特征

进程和程序是两个大相径庭的概念,除了进程具备程序所没有的PCB结构外,还具备下面一些特征:   

(1) 动态性。   (2) 并发性。   (3) 独立性。   (4) 异步性。

 

 2.2.2  进程的基本状态及转换  

1. 进程的三种基本状态

因为多个进程在并发执行时共享系统资源,导致它们在运行过程当中呈现间断性的运行规律,因此进程在其生命周期内可能具备多种状态。通常而言,每个进程至少应处于如下三种基本状态之一:

(1) 就绪(Ready)状态。   (2) 执行(Running)状态。   (3) 阻塞(Block)状态。 

 

 2. 三种基本状态的转换

进程在运行过程当中会常常发生状态的转换。例如,处于就绪状态的进程,在调度程序为之分配了处理机以后即可执行,相应地,其状态就由就绪态转变为执行态;正在执行的进程(当前进程)若是因分配给它的时间片已完而被剥夺处理机暂停执行时,其状态便由执行转为就绪;若是因发生某事件,导致当前进程的执行受阻(例如进程访问某临界资源,而该资源正被其它进程访问时),使之没法继续执行,则该进程状态将由执行转变为阻塞。图2-5示出了进程的三种基本状态,以及各状态之间的转换关系。

图2-5 进程的三种基本状态及其转换

 

3. 建立状态和终止状态

1) 建立状态

  如前所述,进程是由建立而产生。建立一个进程是个很复杂的过程,通常要经过多个步骤才能完成:如首先由进程申请一个空白PCB,并向PCB中填写用于控制和管理进程的信息;而后为该进程分配运行时所必须的资源;最后,把该进程转入就绪状态并插入就绪队列之中。但若是进程所需的资源尚不能获得知足,好比系统尚无足够的内存使进程没法装入其中,此时建立工做还没有完成,进程不能被调度运行,因而把此时进程所处的状态称为建立状态。

2) 终止状态

  进程的终止也要经过两个步骤:首先,是等待操做系统进行善后处理,最后将其PCB清零,并将PCB空间返还系统。当一个进程到达了天然结束点,或是出现了没法克服的错误,或是被操做系统所终结,或是被其余有终止权的进程所终结,它将进入终止状态。进入终止态的进程之后不能再执行,但在操做系统中依然保留一个记录,其中保存状态码和一些计时统计数据,供其余进程收集。一旦其余进程完成了对其信息的提取以后,操做系统将删除该进程,即将其PCB清零,并将该空白PCB返还系统。图2-6示出了增长了建立状态和终止状态后进程的五种状态及转换关系图。

 

图2-6 进程的五种基本状态及转换

 

2.2.3  挂起操做和进程状态的转换

1. 挂起操做的引入   

引入挂起操做的缘由,是基于系统和用户的以下须要:   

(1) 终端用户的须要。   (2) 父进程请求。   (3) 负荷调节的须要。   (4) 操做系统的须要。 

 

 2. 引入挂起原语操做后三个进程状态的转换

在引入挂起原语Suspend和激活原语Active后,在它们的做用下,进程将可能发生如下几种状态的转换:   

(1) 活动就绪→静止就绪。   

(2) 活动阻塞→静止阻塞。   

(3) 静止就绪→活动就绪。   

(4) 静止阻塞→活动阻塞。

 

3. 引入挂起操做后五个进程状态的转换

  如图2-8示出了增长了建立状态和终止状态后具备挂起状态的进程状态及转换图。

  如图2-8所示,引进建立和终止状态后,在进程状态转换时,与图2-7所示的进程五状态转换相比较,要增长考虑下面的几种状况:

  (1)  NULL→建立:   (2) 建立→活动就绪:   (3) 建立→静止就绪:   (4) 执行→终止:

 

图2-7 具备挂起状态的进程状态图

图2-8 具备建立、终止和挂起状态的进程状态图

 

2.2.4  进程管理中的数据结构

1. 操做系统中用于管理控制的数据结构    

在计算机系统中,对于每一个资源和每一个进程都设置了一个数据结构,用于表征其实体,咱们称之为资源信息表或进程信息表,其中包含了资源或进程的标识、描述、状态等信息以及一批指针。经过这些指针,能够将同类资源或进程的信息表,或者同一进程所占用的资源信息表分类连接成不一样的队列,便于操做系统进行查找。 

 如图2-9所示,OS管理的这些数据结构通常分为如下四类:内存表、设备表、文件表和用于进程管理的进程表,一般进程表又被称为进程控制块PCB。 

 

 2. 进程控制块PCB的做用

(1) 做为独立运行基本单位的标志。

(2) 能实现间断性运行方式。

(3) 提供进程管理所须要的信息。

(4) 提供进程调度所须要的信息。

(5) 实现与其它进程的同步与通讯。

 

 3. 进程控制块中的信息 

在进程控制块中,主要包括下述四个方面的信息。 

1) 进程标识符   

进程标识符用于惟一地标识一个进程。一个进程一般有两种标识符:

  (1) 外部标识符。   (2) 内部标识符。

 2) 处理机状态   

处理机状态信息也称为处理机的上下文,主要是由处理机的各类寄存器中的内容组成的。 

 3) 进程调度信息   

在OS进行调度时,必须了解进程的状态及有关进程调度的信息,这些信息包括:

① 进程状态,指明进程的当前状态,它是做为进程调度和对换时的依据;

② 进程优先级,是用于描述进程使用处理机的优先级别的一个整数,优先级高的进程应优先得到处理机;

③ 进程调度所需的其它信息,它们与所采用的进程调度算法有关,好比,进程已等待CPU的时间总和、进程已执行的时间总和等;

④ 事件,是指进程由执行状态转变为阻塞状态所等待发生的事件,即阻塞缘由。

 4) 进程控制信息

是指用于进程控制所必须的信息,它包括:① 程序和数据的地址,进程实体中的程序和数据的内存或外存地(首)址,以便再调度到该进程执行时,能从PCB中找到其程序和数据;② 进程同步和通讯机制,这是实现进程同步和进程通讯时必需的机制,如消息队列指针、信号量等,它们可能所有或部分地放在PCB中;③ 资源清单,在该清单中列出了进程在运行期间所需的所有资源(除CPU之外),另外还有一张已分配到该进程的资源的清单;④ 连接指针,它给出了本进程(PCB)所在队列中的下一个进程的PCB的首地址。

 

4. 进程控制块的组织方式

  在一个系统中,一般可拥有数十个、数百个乃至数千个PCB。为了能对它们加以有效的管理,应该用适当的方式将这些PCB组织起来。目前经常使用的组织方式有如下三种。

(1) 线性方式,即将系统中全部的PCB都组织在一张线性表中,将该表的首址存放在内存的一个专用区域中。该方式实现简单、开销小,但每次查找时都须要扫描整张表,所以适合进程数目很少的系统。图2-10示出了线性表的PCB组织方式。

 

 

图2-10 PCB线性表示意图

 

(2) 连接方式,即把具备相同状态进程的PCB分别经过PCB中的连接字连接成一个队列。这样,能够造成就绪队列、若干个阻塞队列和空白队列等。对就绪队列而言,每每按进程的优先级将PCB从高到低进行排列,将优先级高的进程PCB排在队列的前面。一样,也可把处于阻塞状态进程的PCB根据其阻塞缘由的不一样,排成多个阻塞队列,如等待I/O操做完成的队列和等待分配内存的队列等。图2-11示出了一种连接队列的组织方式。

图2-11 PCB连接队列示意图

 

(3) 索引方式,即系统根据全部进程状态的不一样,创建几张索引表,例如,就绪索引表、阻塞索引表等,并把各索引表在内存的首地址记录在内存的一些专用单元中。在每一个索引表的表目中,记录具备相应状态的某个PCB在PCB表中的地址。图2-12示出了索引方式的PCB组织。

图2-12 按索引方式组织PCB

 

2.3  进 程 控 制

进程控制是进程管理中最基本的功能,主要包括建立新进程、终止已完成的进程、将因发生异常状况而没法继续运行的进程置于阻塞状态、负责进程运行中的状态转换等功能。如当一个正在执行的进程因等待某事件而暂时不能继续执行时,将其转变为阻塞状态,而在该进程所期待的事件出现后,又将该进程转换为就绪状态等。进程控制通常是由OS的内核中的原语来实现的。

 2.3.1  操做系统内核

  1. 支撑功能   (1) 中断处理。   (2) 时钟管理。   (3) 原语操做。

   2. 资源管理功能   (1) 进程管理。   (2) 存储器管理。   (3) 设备管理。 

 

 2.3.2  进程的建立

1. 进程的层次结构

  在OS中,容许一个进程建立另外一个进程,一般把建立进程的进程称为父进程,而把被建立的进程称为子进程。子进程可继续建立更多的孙进程,由此便造成了一个进程的层次结构。如在UNIX中,进程与其子孙进程共同组成一个进程家族(组)。

 

2. 进程图

  为了形象地描述一个进程的家族关系而引入了进程图(Process Graph)。所谓进程图就是用于描述进程间关系的一棵有向树,如图2-13所示。 

图2-13 进程树

 

3. 引发建立进程的事件

  为使程序之间能并发运行,应先为它们分别建立进程。致使一个进程去建立另外一个进程的典型事件有四类:

  (1) 用户登陆。   (2) 做业调度。   (3) 提供服务。   (4) 应用请求。 

 

 4. 进程的建立(Creation of Process)

  在系统中每当出现了建立新进程的请求后,OS便调用进程建立原语Creat按下述步骤建立一个新进程:

  (1) 申请空白PCB,为新进程申请得到惟一的数字标识符,并从PCB集合中索取一个空白PCB。

  (2) 为新进程分配其运行所需的资源,包括各类物理和逻辑资源,如内存、文件、I/O设备和CPU时间等。

  (3) 初始化进程控制块(PCB)。

  (4) 若是进程就绪队列可以接纳新进程,便将新进程插入就绪队列。

 

 2.3.3  进程的终止

  1. 引发进程终止(Termination of Process)的事件

  (1) 正常结束   (2) 异常结束   (3) 外界干预 

 

  2. 进程的终止过程

  若是系统中发生了要求终止进程的某事件,OS便调用进程终止原语,按下述过程去终止指定的进程:

  (1) 根据被终止进程的标识符,从PCB集合中检索出该进程的PCB,从中读出该进程的状态;

  (2) 若被终止进程正处于执行状态,应当即终止该进程的执行,并置调度标志为真,用于指示该进程被终止后应从新进行调度;

  (3) 若该进程还有子孙进程,还应将其全部子孙进程也都予以终止,以防它们成为不可控的进程;

  (4) 将被终止进程所拥有的所有资源或者归还给其父进程,或者归还给系统;

  (5) 将被终止进程(PCB)从所在队列(或链表)中移出,等待其它程序来搜集信息。

 

2.3.4  进程的阻塞与唤醒

  1. 引发进程阻塞和唤醒的事件

  有下述几类事件会引发进程阻塞或被唤醒:

  (1) 向系统请求共享资源失败。   (2) 等待某种操做的完成。   (3) 新数据还没有到达。   (4) 等待新任务的到达。

 

   2. 进程阻塞过程

  正在执行的进程,若是发生了上述某事件,进程便经过调用阻塞原语block将本身阻塞。可见,阻塞是进程自身的一种主动行为。进入block过程后,因为该进程还处于执行状态,因此应先当即中止执行,把进程控制块中的现行状态由“执行”改成阻塞,并将PCB插入阻塞队列。若是系统中设置了因不一样事件而阻塞的多个阻塞队列,则应将本进程插入到具备相同事件的阻塞队列。最后,转调度程序进行从新调度,将处理机分配给另外一就绪进程,并进行切换,亦即,保留被阻塞进程的处理机状态,按新进程的PCB中的处理机状态设置CPU的环境。 

 

  3. 进程唤醒过程

  当被阻塞进程所期待的事件发生时,好比它所启动的I/O操做已完成,或其所期待的数据已经到达,则由有关进程(好比提供数据的进程)调用唤醒原语wakeup,将等待该事件的进程唤醒。wakeup执行的过程是:首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB中的现行状态由阻塞改成就绪,而后再将该PCB插入到就绪队列中。

 

2.3.5  进程的挂起与激活

  1. 进程的挂起   2. 进程的激活过程

 

 

 2.4 进 程 同 步

  在OS中引入进程后,一方面可使系统中的多道程序并发执行,这不只能有效地改善资源利用率,还可显著地提升系统的吞吐量,但另外一方面却使系统变得更加复杂。若是不能采起有效的措施,对多个进程的运行进行妥善的管理,必然会由于这些进程对系统资源的无序争夺给系统形成混乱。导致每次处理的结果存在着不肯定性,即显现出其不可再现性。

2.4.1 进程同步的基本概念

1. 两种形式的制约关系

  1) 间接相互制约关系

  2) 直接相互制约关系

 

2. 临界资源(Critical Resouce)

  在第一章中咱们曾经介绍过,许多硬件资源如打印机、 磁带机等,都属于临界资源,诸进程间应采起互斥方式,实现对这种资源的共享。 

 

3. 临界区(critical section)

  由前所述可知,不管是硬件临界资源仍是软件临界资源,多个进程必须互斥地对它进行访问。人们把在每一个进程中访问临界资源的那段代码称为临界区(critical section)。 

 

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

  为实现进程互斥地进入本身的临界区,可用软件方法,更多的是在系统中设置专门的同步机构来协调各进程间的运行。全部同步机制都应遵循下述四条准则:

  (1) 空闲让进。   (2) 忙则等待。   (3) 有限等待。   (4) 让权等待。

 

 2.4.2  硬件同步机制

  虽然能够利用软件方法解决诸进程互斥进入临界区的问题,但有必定难度,而且存在很大的局限性,于是如今已不多采用。相应地,目前许多计算机已提供了一些特殊的硬件指令,容许对一个字中的内容进行检测和修正,或者是对两个字的内容进行交换等。可利用这些特殊的指令来解决临界区问题。

 

 1. 关中断

  关中断是实现互斥的最简单的方法之一。在进入锁测试以前关闭中断,直到完成锁测试并上锁以后才能打开中断。这样,进程在临界区执行期间,计算机系统不响应中断,从而不会引起调度,也就不会发生进程或线程切换。由此,保证了对锁的测试和关锁操做的连续性和完整性,有效地保证了互斥。可是,关中断的方法存在许多缺点:① 滥用关中断权力可能致使严重后果;② 关中断时间过长,会影响系统效率,限制了处理器交叉执行程序的能力;③ 关中断方法也不适用于多CPU 系统,由于在一个处理器上关中断并不能防止进程在其它处理器上执行相同的临界段代码。

 

2. 利用Test-and-Set指令实现互斥

  这是一种借助一条硬件指令——“测试并创建”指令TS(Test-and-Set)以实现互斥的方法。在许多计算机中都提供了这种指令。 

 

3. 利用Swap指令实现进程互斥

  该指令称为对换指令,在Intel 80x86中又称为XCHG指令,用于交换两个字的内容。 

 

 2.4.3 信号量机制

1. 整型信号量

  最初由Dijkstra把整型信号量定义为一个用于表示资源数目的整型量S,它与通常整型量不一样,除初始化外,仅能经过两个标准的原子操做(Atomic Operation) wait(S)和signal(S)来访问。很长时间以来,这两个操做一直被分别称为P、V操做。 

 

2. 记录型信号量

  在整型信号量机制中的wait操做,只要是信号量S≤0,就会不断地测试。所以,该机制并未遵循“让权等待”的准则,而是使进程处于“忙等”的状态。记录型信号量机制则是一种不存在“忙等”现象的进程同步机制。但在采起了“让权等待”的策略后,又会出现多个进程等待访问同一临界资源的状况。为此,在信号量机制中,除了须要一个用于表明资源数目的整型变量value外,还应增长一个进程链表指针list,用于连接上述的全部等待进程。 

 

 3.  AND型信号量

  前面所述的进程互斥问题针对的是多个并发进程仅共享一个临界资源的状况。在有些应用场合,是一个进程每每须要得到两个或更多的共享资源后方能执行其任务。假定现有两个进程A和B,它们都要求访问共享数据D和E,固然,共享数据都应做为临界资源。 

 

 4. 信号量集

  在前面所述的记录型信号量机制中,wait(S)或signal(S)操做仅能对信号量施以加1或减1操做,意味着每次只能对某类临界资源进行一个单位的申请或释放。当一次须要N个单位时,便要进行N次wait(S)操做,这显然是低效的,甚至会增长死锁的几率。此外,在有些状况下,为确保系统的安全性,当所申请的资源数量低于某一下限值时,还必须进行管制,不予以分配。所以,当进程申请某类临界资源时,在每次分配以前,都必须测试资源的数量,判断是否大于可分配的下限值,决定是否予以分配。

 

 2.4.4 信号量的应用

1. 利用信号量实现进程互斥

为使多个进程能互斥地访问某临界资源,只需为该资源设置一互斥信号量mutex,并设其初始值为1,而后将各进程访问该资源的临界区CS置于wait(mutex)和signal(mutex)操做之间便可。 

 

2. 利用信号量实现前趋关系

  还可利用信号量来描述程序或语句之间的前趋关系。设有两个并发执行的进程P1和P2。P1中有语句S1;P2中有语句S2。咱们但愿在S1执行后再执行S2。为实现这种前趋关系,只需使进程P1和P2共享一个公用信号量S,并赋予其初值为0,将signal(S)操做放在语句S1后面,而在S2语句前面插入wait(S)操做,即

  在进程P1中,用S1;signal(S);

  在进程P2中,用wait(S);S2;

因为S被初始化为0,这样,若P2先执行一定阻塞,只有在进程P1执行完S1; signal(S);操做后使S增为1时,P2进程方能成功执行语句S2。一样,咱们能够利用信号量按照语句间的前趋关系(见图2-14),写出一个更为复杂的可并发执行的程序。 

 

图2-14 前趋图举例

 

2.4.5 管程机制

1.管程的定义

  系统中的各类硬件资源和软件资源都可用数据结构抽象地描述其资源特性,即用少许信息和对该资源所执行的操做来表征该资源,而忽略它们的内部结构和实现细节。 

由上述的定义可知,管程由四部分组成:① 管程的名称;② 局部于管程的共享数据结构说明;③ 对该数据结构进行操做的一组过程;④ 对局部于管程的共享数据设置初始值的语句。图2-15是一个管程的示意图。

 

图2-15 管程的示意图

 

2. 条件变量

  在利用管程实现进程同步时,必须设置同步工具,如两个同步操做原语wait和signal。当某进程经过管程请求得到临界资源而未能知足时,管程便调用wait原语使该进程等待,并将其排在等待队列上,如图2-13所示。仅当另外一进程访问完成并释放该资源以后,管程才又调用signal原语,唤醒等待队列中的队首进程。

 

 

 2.5 经典进程的同步问题

  在多道程序环境下,进程同步问题十分重要,也是至关有趣的问题,于是吸引了很多学者对它进行研究,由此而产生了一系列经典的进程同步问题,其中较有表明性的是“生产者—消费者”问题、“读者—写者问题”、“哲学家进餐问题”等等。经过对这些问题的研究和学习,能够帮助咱们更好地理解进程同步的概念及实现方法。

 2.5.1 生产者-消费者问题

1. 利用记录型信号量解决生产者-消费者问题

  假定在生产者和消费者之间的公用缓冲池中具备n个缓冲区,这时可利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量。又假定这些生产者和消费者相互等效,只要缓冲池未满,生产者即可将消息送入缓冲池;只要缓冲池未空,消费者即可从缓冲池中取走一个消息。 

2. 利用AND信号量解决生产者-消费者问题

  对于生产者-消费者问题,也可利用AND信号量来解决,即用Swait(empty,mutex)来代替wait(empty)和wait(mutex);用Ssignal(mutex,full)来代替signal(mutex)和signal(full);用Swait(full,mutex)代替wait(full)和wait(mutex),以及用Ssignal(mutex,empty)代替Signal(mutex)和Signal(empty)。 

3. 利用管程解决生产者-消费者问题

  在利用管程方法来解决生产者-消费者问题时,首先即是为它们创建一个管程,并命名为procducerconsumer,或简称为PC。其中包括两个过程:

  (1)  put(x)过程。   (2)  get(x)过程。 

 对于条件变量notfull和notempty,分别有两个过程cwait和csignal对它们进行操做:

  (1)  cwait(condition)过程:当管程被一个进程占用时,其余进程调用该过程时阻塞,并挂在条件condition的队列上。

  (2)  csignal(condition)过程:唤醒在cwait执行后阻塞在条件condition队列上的进程,若是这样的进程不止一个,则选择其中一个实施唤醒操做;若是队列为空,则无操做而返回。

 

 2.5.2 哲学家进餐问题

  1. 利用记录型信号量解决哲学家进餐问题

  经分析可知,放在桌子上的筷子是临界资源,在一段时间内只容许一位哲学家使用。为了实现对筷子的互斥使用,能够用一个信号量表示一只筷子,由这五个信号量构成信号量数组。 

 2. 利用AND信号量机制解决哲学家进餐问题

  在哲学家进餐问题中,要求每一个哲学家先得到两个临界资源(筷子)后方能进餐,这在本质上就是前面所介绍的AND同步问题,故用AND信号量机制可得到最简洁的解法。

 

 2.5.3 读者-写者问题

1. 利用记录型信号量解决读者-写者问题

  为实现Reader与Writer进程间在读或写时的互斥而设置了一个互斥信号量Wmutex。另外,再设置一个整型变量Readcount表示正在读的进程数目。因为只要有一个Reader进程在读,便不容许Writer进程去写。所以,仅当Readcount=0,表示尚无Reader进程在读时,Reader进程才须要执行Wait(Wmutex)操做。若wait(Wmutex)操做成功,Reader进程即可去读,相应地,作Readcount+1操做。 

 2. 利用信号量集机制解决读者-写者问题

  这里的读者—写者问题,与前面的略有不一样,它增长了一个限制,即最多只容许RN个读者同时读。为此,又引入了一个信号量L,并赋予其初值为RN,经过执行wait(L, 1, 1)操做来控制读者的数目,每当有一个读者进入时,就要先执行wait(L, 1, 1)操做,使L的值减1。当有RN个读者进入读后,L便减为0,第RN + 1个读者要进入读时,必然会因wait(L, 1, 1)操做失败而阻塞。 

 

 2.6  进 程 通 信

  进程通讯是指进程之间的信息交换。因为进程的互斥与同步,须要在进程间交换必定的信息,故很多学者将它们也归为进程通讯,但只能把它们称为低级进程通讯。咱们以信号量机制为例来讲明,它们之因此低级的缘由在于:① 效率低,生产者每次只能向缓冲池投放一个产品(消息),消费者每次只能从缓冲区中取得一个消息;② 通讯对用户不透明,OS只为进程之间的通讯提供了共享存储器。 

  在进程之间要传送大量数据时,应当利用OS提供的高级通讯工具,该工具最主要的特色是:

  (1) 使用方便。OS隐藏了实现进程通讯的具体细节,向用户提供了一组用于实现高级通讯的命令(原语),用户可方便地直接利用它实现进程之间的通讯。或者说,通讯过程对用户是透明的。这样就大大减小了通讯程序编制上的复杂性。

  (2) 高效地传送大量数据。用户可直接利用高级通讯命令(原语)高效地传送大量的数据。

 

 2.6.1 进程通讯的类型

1. 共享存储器系统(Shared-Memory System)

  在共享存储器系统中,相互通讯的进程共享某些数据结构或共享存储区,进程之间可以经过这些空间进行通讯。据此,又可把它们分红如下两种类型:

  (1) 基于共享数据结构的通讯方式。   (2) 基于共享存储区的通讯方式。

 

 2. 管道(pipe)通讯系统

  所谓“管道”,是指用于链接一个读进程和一个写进程以实现它们之间通讯的一个共享文件,又名pipe文件。向管道(共享文件)提供输入的发送进程(即写进程)以字符流形式将大量的数据送入管道;而接受管道输出的接收进程(即读进程)则从管道中接收(读)数据。因为发送进程和接收进程是利用管道进行通讯的,故又称为管道通讯。这种方式独创于UNIX系统,因为它能有效地传送大量数据,于是又被引入到许多其它操做系统中。

 为了协调双方的通讯,管道机制必须提供如下三方面的协调能力:① 互斥,即当一个进程正在对pipe执行读/写操做时,其它(另外一)进程必须等待。② 同步,指当写(输入)进程把必定数量(如4 KB)的数据写入pipe,便去睡眠等待,直到读(输出)进程取走数据后再把它唤醒。当读进程读一空pipe时,也应睡眠等待,直至写进程将数据写入管道后才将之唤醒。③ 肯定对方是否存在,只有肯定了对方已存在时才能进行通讯。

 

3. 消息传递系统(Message passing system)

  在该机制中,进程没必要借助任何共享存储区或数据结构,而是以格式化的消息 (message)为单位,将通讯的数据封装在消息中,并利用操做系统提供的一组通讯命令(原语),在进程间进行消息传递,完成进程间的数据交换。

  基于消息传递系统的通讯方式属于高级通讯方式,因其实现方式的不一样,可进一步分红两类:

  (1) 直接通讯方式   (2) 间接通讯方式 

 

4. 客户机-服务器系统(Client-Server system)

1) 套接字(Socket)

  套接字起源于20世纪70年代加州大学伯克利分校版本的UNIX(即BSD Unix),是UNIX 操做系统下的网络通讯接口。一开始,套接字被设计用在同一台主机上多个应用程序之间的通讯(即进程间的通讯),主要是为了解决多对进程同时通讯时端口和物理线路的多路复用问题。随着计算机网络技术的发展以及UNIX 操做系统的普遍使用,套接字已逐渐成为最流行的网络通讯程序接口之一。

2) 远程过程调用和远程方法调用

  远程过程(函数)调用RPC(Remote Procedure Call),是一个通讯协议,用于经过网络链接的系统。该协议容许运行于一台主机(本地)系统上的进程调用另外一台主机(远程)系统上的进程,而对程序员表现为常规的过程调用,无需额外地为此编程。若是涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程方法调用。

  实际上,远程过程调用的主要步骤是:

  (1) 本地过程调用者以通常方式调用远程过程在本地关联的客户存根,传递相应的参数,而后将控制权转移给客户存根;

  (2) 客户存根执行,完成包括过程名和调用参数等信息的消息创建,将控制权转移给本地客户进程;

  (3) 本地客户进程完成与服务器的消息传递,将消息发送到远程服务器进程;

  (4) 远程服务器进程接收消息后转入执行,并根据其中的远程过程名找到对应的服务器存根,将消息转给该存根;

  (5) 该服务器存根接到消息后,由阻塞状态转入执行状态,拆开消息从中取出过程调用的参数,而后以通常方式调用服务器上关联的过程;

  (6) 在服务器端的远程过程运行完毕后,将结果返回给与之关联的服务器存根;

  (7) 该服务器存根得到控制权运行,将结果打包为消息,并将控制权转移给远程服务器进程;

  (8) 远程服务器进程将消息发送回客户端;

  (9) 本地客户进程接收到消息后,根据其中的过程名将消息存入关联的客户存根,再将控制权转移给客户存根;

  (10) 客户存根从消息中取出结果,返回给本地调用者进程,并完成控制权的转移。

 

2.6.2 消息传递通讯的实现方式

1. 直接消息传递系统

  在直接消息传递系统中采用直接通讯方式,即发送进程利用OS所提供的发送命令(原语),直接把消息发送给目标进程。

1) 直接通讯原语

  (1) 对称寻址方式。   (2) 非对称寻址方式。

2) 消息的格式

  在消息传递系统中所传递的消息,必须具备必定的消息格式。在单机系统环境中,因为发送进程和接收进程处于同一台机器中,有着相同的环境,因此消息的格式比较简单,可采用比较短的定长消息格式,以减小对消息的处理和存储开销。该方式可用于办公自动化系统中,为用户提供快速的便笺式通讯。但这种方式对于须要发送较长消息的用户是不方便的。为此,可采用变长的消息格式,即进程所发送消息的长度是可变的。对于变长消息,系统不管在处理方面仍是存储方面,均可能会付出更多的开销,但其优势在于方便了用户。

3) 进程的同步方式

  在进程之间进行通讯时,一样须要有进程同步机制,以使诸进程间能协调通讯。不管是发送进程仍是接收进程,在完成消息的发送或接收后,都存在两种可能性,即进程或者继续发送(或接收)或者阻塞。 

4) 通讯链路

  为使在发送进程和接收进程之间能进行通讯,必须在二者之间创建一条通讯链路。有两种方式创建通讯链路。第一种方式是:由发送进程在通讯以前用显式的“创建链接”命令(原语)请求系统为之创建一条通讯链路,在链路使用完后拆除链路。 

 

2. 信箱通讯

  1) 信箱的结构

  信箱定义为一种数据结构。在逻辑上,能够将其分为两个部分:

  (1) 信箱头   (2) 信箱体

图2-16 双向信箱示意图

2) 信箱通讯原语

  系统为邮箱通讯提供了若干条原语,分别用于:

  (1) 邮箱的建立和撤消。   (2) 消息的发送和接收。

 3) 信箱的类型

  邮箱可由操做系统建立,也可由用户进程建立,建立者是邮箱的拥有者。据此,可把邮箱分为如下三类:

  (1) 私用邮箱。   (2) 公用邮箱。   (3) 共享邮箱。 

 

 

 2.6.3 直接消息传递系统实例

  消息缓冲队列通讯机制首先由美国的Hansan提出,并在RC 4000系统上实现,后来被普遍应用于本地进程之间的通讯中。在这种通讯机制中,发送进程利用Send原语将消息直接发送给接收进程;接收进程则利用Receive原语接收消息。

 1. 消息缓冲队列通讯机制中的数据结构

  (1) 消息缓冲区。   (2) PCB中有关通讯的数据项。

 

 2. 发送原语

  发送进程在利用发送原语发送消息以前,应先在本身的内存空间设置一发送区a,如图2-17所示,把待发送的消息正文、发送进程标识符、消息长度等信息填入其中,而后调用发送原语,把消息发送给目标(接收)进程。发送原语首先根据发送区a中所设置的消息长度a.size来申请一缓冲区i,接着,把发送区a中的信息复制到缓冲区i中。为了能将i挂在接收进程的消息队列mq上,应先得到接收进程的内部标识符j,而后将i挂在j.mq上。因为该队列属于临界资源,故在执行insert操做的先后都要执行wait和signal操做。 

图2-17 消息缓冲通讯

 

3. 接收原语

  接收进程调用接收原语receive(b),从本身的消息缓冲队列mq中摘下第一个消息缓冲区i,并将其中的数据复制到以b为首址的指定消息接收区内。 

 

 

 2.7  线程(Threads)的基本概念

2.7.1  线程的引入

  若是说,在OS中引入进程的目的是为了使多个程序能并发执行,以提升资源利用率和系统吞吐量,那么,在操做系统中再引入线程,则是为了减小程序在并发执行时所付出的时空开销,使OS具备更好的并发性。

 

 1. 进程的两个基本属性

  首先让咱们来回顾进程的两个基本属性:

  ① 进程是一个可拥有资源的独立单位,一个进程要能独立运行,它必须拥有必定的资源,包括用于存放程序正文、数据的磁盘和内存地址空间,以及它在运行时所须要的I/O设备、已打开的文件、信号量等;

   ② 进程同时又是一个可独立调度和分派的基本单位,一个进程要能独立运行,它还必须是一个可独立调度和分派的基本单位。每一个进程在系统中有惟一的PCB,系统可根据其PCB感知进程的存在,也能够根据其PCB中的信息,对进程进行调度,还可将断点信息保存在其PCB中。反之,再利用进程PCB中的信息来恢复进程运行的现场。正是因为进程有这两个基本属性,才使进程成为一个能独立运行的基本单位,从而也就构成了进程并发执行的基础。

 

 2. 程序并发执行所需付出的时空开销

  为使程序能并发执行,系统必须进行如下的一系列操做:

  (1) 建立进程,系统在建立一个进程时,必须为它分配其所必需的、除处理机之外的全部资源,如内存空间、I/O设备,以及创建相应的PCB;

  (2) 撤消进程,系统在撤消进程时,又必须先对其所占有的资源执行回收操做,而后再撤消PCB;

  (3) 进程切换,对进程进行上下文切换时,须要保留当前进程的CPU环境,设置新选中进程的CPU环境,于是须花费很多的处理机时间。

 

 3. 线程——做为调度和分派的基本单位

  如何能使多个程序更好地并发执行,同时又尽可能减小系统的开销,已成为近年来设计操做系统时所追求的重要目标。有很多研究操做系统的学者们想到,要设法将进程的上述两个属性分开,由OS分开处理,亦即并不把做为调度和分派的基本单位也同时做为拥有资源的单位,以作到“轻装上阵”;而对于拥有资源的基本单位,又不对之施以频繁的切换。正是在这种思想的指导下,造成了线程的概念。

 

 

 2.7.2  线程与进程的比较

  1. 调度的基本单位   2. 并发性   3. 拥有资源   4. 独立性   5. 系统开销   6. 支持多处理机系统

 

  1 进程与线程的一个简单解释
  2 进程(process)和线程(thread)是操做系统的基本概念,可是它们比较抽象,不容易掌握。
  3 
  4 最近,我读到一篇材料,发现有一个很好的类比,能够把它们解释地清晰易懂。
  5 
  6 1.
  7 
  8 
  9 
 10 计算机的核心是CPU,它承担了全部的计算任务。它就像一座工厂,时刻在运行。
 11 
 12 2.
 13 
 14 
 15 
 16 假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其余车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。
 17 
 18 3.
 19 
 20 
 21 
 22 进程就比如工厂的车间,它表明CPU所能处理的单个任务。任一时刻,CPU老是运行一个进程,其余进程处于非运行状态。
 23 
 24 4.
 25 
 26 
 27 
 28 一个车间里,能够有不少工人。他们协同完成一个任务。
 29 
 30 5.
 31 
 32 
 33 
 34 线程就比如车间里的工人。一个进程能够包括多个线程。
 35 
 36 6.
 37 
 38 
 39 
 40 车间的空间是工人们共享的,好比许多房间是每一个工人均可以进出的。这象征一个进程的内存空间是共享的,每一个线程均可以使用这些共享内存。
 41 
 42 7.
 43 
 44 
 45 
 46 但是,每间房间的大小不一样,有些房间最多只能容纳一我的,好比厕所。里面有人的时候,其余人就不能进去了。这表明一个线程使用某些共享内存时,其余线程必须等它结束,才能使用这一块内存。
 47 
 48 8.
 49 
 50 
 51 
 52 一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。
 53 
 54 9.
 55 
 56 
 57 
 58 还有些房间,能够同时容纳n我的,好比厨房。也就是说,若是人数大于n,多出来的人只能在外面等着。这比如某些内存区域,只能供给固定数目的线程使用。
 59 
 60 10.
 61 
 62 
 63 
 64 这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种作法叫作"信号量"(Semaphore),用来保证多个线程不会互相冲突。
 65 
 66 不难看出,mutex是semaphore的一种特殊状况(n=1时)。也就是说,彻底能够用后者替代前者。可是,由于mutex较为简单,且效率高,因此在必须保证资源独占的状况下,仍是采用这种设计。
 67 
 68 11.
 69 
 70 
 71 
 72 操做系统的设计,所以能够归结为三点:
 73 
 74 (1)以多进程形式,容许多个任务同时运行;
 75 
 76 (2)以多线程形式,容许单个任务分红不一样的部分运行;
 77 
 78 (3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另外一方面容许进程之间和线程之间共享资源。
 79 
 80 (完)
 81 
 82 转:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
 83 
 84  
 85 
 86 这里有一段知乎上的解释:
 87 
 88 看见上面几位的回答我真的是醉了。说几句个人理解。
 89 
 90 首先来一句归纳的总论:进程和线程都是一个时间段的描述,是CPU工做时间段的描述。
 91 
 92 下面细说背景:
 93 CPU+RAM+各类资源(好比显卡,光驱,键盘,GPS, 等等外设)构成咱们的电脑,可是电脑的运行,实际就是CPU和相关寄存器以及RAM之间的事情。
 94 
 95 一个最最基础的事实:CPU太快,太快,太快了,寄存器仅仅可以追的上他的脚步,RAM和别的挂在各总线上的设备彻底是望其项背。那当多个任务要执行的时候怎么办呢?轮流着来?或者谁优先级高谁来?无论怎么样的策略,一句话就是在CPU看来就是轮流着来。
 96 
 97 一个必须知道的事实:执行一段程序代码,实现一个功能的过程介绍 ,当获得CPU的时候,相关的资源必须也已经就位,就是显卡啊,GPS啊什么的必须就位,而后CPU开始执行。这里除了CPU之外全部的就构成了这个程序的执行环境,也就是咱们所定义的程序上下文。当这个程序执行完了,或者分配给他的CPU执行时间用完了,那它就要被切换出去,等待下一次CPU的临幸。在被切换出去的最后一步工做就是保存程序上下文,由于这个是下次他被CPU临幸的运行环境,必须保存。
 98 
 99 串联起来的事实:前面讲过在CPU看来全部的任务都是一个一个的轮流执行的,具体的轮流方法就是:先加载程序A的上下文,而后开始执行A,保存程序A的上下文,调入下一个要执行的程序B的程序上下文,而后开始执行B,保存程序B的上下文。。。。
100 
101 ========= 重要的东西出现了========
102 进程和线程就是这样的背景出来的,两个名词不过是对应的CPU时间段的描述,名词就是这样的功能。
103 进程就是包换上下文切换的程序执行时间总和 = CPU加载上下文+CPU执行+CPU保存上下文
104 线程是什么呢?
105 进程的颗粒度太大,每次都要有上下的调入,保存,调出。若是咱们把进程比喻为一个运行在电脑上的软件,那么一个软件的执行不多是一条逻辑执行的,一定有多个分支和多个程序段,就比如要实现程序A,实际分红 a,b,c等多个块组合而成。那么这里具体的执行就可能变成:
106 
107 程序A获得CPU =》CPU加载上下文,开始执行程序A的a小段,而后执行A的b小段,而后再执行A的c小段,最后CPU保存A的上下文。
108 
109 这里a,b,c的执行是共享了A的上下文,CPU在执行的时候没有进行上下文切换的。这里的a,b,c就是线程,也就是说线程是共享了进程的上下文环境,的更为细小的CPU时间段。
110 
111 到此全文结束,再一个总结:
112 
113 进程和线程都是一个时间段的描述,是CPU工做时间段的描述,不过是颗粒大小不一样。
114  
115 来自 https://www.zhihu.com/question/25532384
116 好文要顶 关注我 收藏该文    
线程和进程

 

 

 2.7.3  线程的状态和线程控制块

1. 线程运行的三个状态   

  与传统的进程同样,在各线程之间也存在着共享资源和相互合做的制约关系,导致线程在运行时也具备间断性。相应地,线程在运行时也具备下述三种基本状态:

  (1) 执行状态,表示线程已得到处理机而正在运行;

  (2) 就绪状态,指线程已具有了各类执行条件,只须再得到CPU即可当即执行;

  (3) 阻塞状态,指线程在执行中因某事件受阻而处于暂停状态,例如,当一个线程执行从键盘读入数据的系统调用时,该线程就被阻塞。

 

 2. 线程控制块TCB

  如同每一个进程有一个进程控制块同样,系统也为每一个线程配置了一个线程控制块TCB,将全部用于控制和管理线程的信息记录在线程控制块中。

 

 3. 多线程OS中的进程属性     

  一般在多线程OS中的进程都包含了多个线程,并为它们提供资源。OS支持在一个进程中的多个线程能并发执行,但此时的进程就再也不做为一个执行的实体。多线程OS中的进程有如下属性:

  (1) 进程是一个可拥有资源的基本单位。   (2) 多个线程可并发执行。   (3) 进程已不是可执行的实体。

 

 2.8  线 程 的 实 现

2.8.1  线程的实现方式

  线程已在许多系统中实现,但各系统的实现方式并不彻底相同。在有的系统中,特别是一些数据库管理系统,如infomix所实现的是用户级线程; 而另外一些系统(如Macintosh和OS/2操做系统)所实现的是内核支持线程;还有一些系统如Solaris操做系统,则同时实现了这两种类型的线程。

 

1. 内核支持线程KST(Kernel Supported Threads)

  在OS中的全部进程,不管是系统进程仍是用户进程,都是在操做系统内核的支持下运行的,是与内核紧密相关的。而内核支持线程KST一样也是在内核的支持下运行的,它们的建立、阻塞、撤消和切换等,也都是在内核空间实现的。为了对内核线程进行控制和管理,在内核空间也为每个内核线程设置了一个线程控制块,内核根据该控制块而感知某线程的存在,并对其加以控制。当前大多数OS都支持内核支持线程。

这种线程实现方式主要有四个主要优势:

  (1) 在多处理器系统中,内核可以同时调度同一进程中的多个线程并行执行;

  (2) 若是进程中的一个线程被阻塞了,内核能够调度该进程中的其它线程占有处理器运行,也能够运行其它进程中的线程;

  (3) 内核支持线程具备很小的数据结构和堆栈,线程的切换比较快,切换开销小;

  (4) 内核自己也能够采用多线程技术,能够提升系统的执行速度和效率。

 

 2. 用户级线程ULT(User Level Threads)

  用户级线程是在用户空间中实现的。对线程的建立、 撤消、同步与通讯等功能,都无需内核的支持,即用户级线程是与内核无关的。在一个系统中的用户级线程的数目能够达到数百个至数千个。因为这些线程的任务控制块都是设置在用户空间,而线程所执行的操做也无需内核的帮助,于是内核彻底不知道用户级线程的存在。

 使用用户级线程方式有许多优势:

  (1) 线程切换不须要转换到内核空间。

  (2) 调度算法能够是进程专用的。

  (3) 用户级线程的实现与OS平台无关,由于对于线程管理的代码是属于用户程序的一部分,全部的应用程序均可以对之进行共享。 

而用户级线程方式的主要缺点则在于:

  (1) 系统调用的阻塞问题。在基于进程机制的OS中,大多数系统调用将使进程阻塞,所以,当线程执行一个系统调用时,不只该线程被阻塞,并且,进程内的全部线程会被阻塞。而在内核支持线程方式中,则进程中的其它线程仍然能够运行。

  (2) 在单纯的用户级线程实现方式中,多线程应用不能利用多处理机进行多重处理的优势,内核每次分配给一个进程的仅有一个CPU,所以,进程中仅有一个线程能执行,在该线程放弃CPU以前,其它线程只能等待。

 

 3. 组合方式

  有些OS把用户级线程和内核支持线程两种方式进行组合,提供了组合方式ULT/KST 线程。在组合方式线程系统中,内核支持多个内核支持线程的创建、调度和管理,同时,也容许用户应用程序创建、调度和管理用户级线程。 

 

图2-18  多线程模型

 

2.8.2  线程的实现

1. 内核支持线程的实现

  在仅设置了内核支持线程的OS中,一种可能的线程控制方法是,系统在建立一个新进程时,便为它分配一个任务数据区PTDA(Per Task Data Area),其中包括若干个线程控制块TCB空间,如图2-19所示。 

 

图2-19 任务数据区空间

 

2. 用户级线程的实现

  1) 运行时系统(Runtime System)

  所谓“运行时系统”,实质上是用于管理和控制线程的函数(过程)的集合,其中包括用于建立和撤消线程的函数、线程同步和通讯的函数,以及实现线程调度的函数等。正由于有这些函数,才能使用户级线程与内核无关。运行时系统中的全部函数都驻留在用户空间,并做为用户级线程与内核之间的接口。

   2) 内核控制线程

  这种线程又称为轻型进程LWP(Light Weight Process)。每个进程均可拥有多个LWP,同用户级线程同样,每一个LWP都有本身的数据结构(如TCB),其中包括线程标识符、优先级、状态,另外还有栈和局部存储区等。LWP也能够共享进程所拥有的资源。LWP可经过系统调用来得到内核提供的服务,这样,当一个用户级线程运行时,只须将它链接到一个LWP上,此时它便具备了内核支持线程的全部属性。这种线程实现方式就是组合方式。

图2-20 利用轻型进程做为中间系统

 

 2.8.3  线程的建立和终止

1. 线程的建立

  应用程序在启动时,一般仅有一个线程在执行,人们把线程称为“初始化线程”,它的主要功能是用于建立新线程。在建立新线程时,须要利用一个线程建立函数(或系统调用),并提供相应的参数,如指向线程主程序的入口指针、堆栈的大小,以及用于调度的优先级等。在线程的建立函数执行完后,将返回一个线程标识符供之后使用。

 2. 线程的终止

  当一个线程完成了本身的任务(工做)后,或是线程在运行中出现异常状况而须被强行终止时,由终止线程经过调用相应的函数(或系统调用)对它执行终止操做。但有些线程(主要是系统线程),它们一旦被创建起来以后,便一直运行下去而不被终止。在大多数的OS中,线程被停止后并不当即释放它所占有的资源,只有当进程中的其它线程执行了分离函数后,被终止的线程才与资源分离,此时的资源才能被其它线程利用。

 

习    题 

  1. 什么是前趋图? 为何要引入前趋图?

  2. 试画出下面四条语句的前趋图:

    S1: a = x+y;

    S2: b = z+1;

    S3: c = a-b;

    S4: w = c+1;

  3. 为何程序并发执行会产生间断性特征?

  4. 程序并发执行时为何会失去封闭性和可再现性? 

    5. 在操做系统中为何要引入进程的概念? 它会产生什么样的影响?

  6. 试从动态性、并发性和独立性上比较进程和程序。

  7. 试说明PCB的做用具体表如今哪几个方面,为何说PCB是进程存在的惟一标志?

  8.  PCB提供了进程管理和进程调度所须要的哪些信息?

  9. 进程控制块的组织方式有哪几种?

  10. 何谓操做系统内核? 内核的主要功能是什么?

  11. 试说明进程在三个基本状态之间转换的典型缘由。

  12. 为何要引入挂起状态? 该状态有哪些性质?13. 在进行进程切换时,所要保存的处理机状态信息有哪些?

  14. 试说明引发进程建立的主要事件。

  15. 试说明引发进程被撤消的主要事件。

  16. 在建立一个进程时所要完成的主要工做是什么?

  17. 在撤消一个进程时所要完成的主要工做是什么?

  18. 试说明引发进程阻塞或被唤醒的主要事件是什么?

  19. 为何要在OS中引入线程?

  20. 试说明线程具备哪些属性?

   21. 试从调度性、并发性、拥有资源及系统开销方面对进程和线程进行比较。

  22. 线程控制块TCB中包含了哪些内容?

  23. 何谓用户级线程和内核支持线程?

  24. 试说明用户级线程的实现方法。

  25. 试说明内核支持线程的实现方法。

  26. 多线程模型有哪几种类型? 多对一模型有何优缺点? 

 

 

线程:http://www.javashuo.com/article/p-wiueyzzz-hc.html

 

 

 

 

相关文章
相关标签/搜索