【操作系统】知识梳理(二)进程的描述与控制

2.1 进程的基本概念

2.1.1 前趋图

前趋图是一个有向无循环图,可用来描述程序段或进程之间执行的先后次序关系。前趋图中的每个结点表示-一个程序段或一个进程,结点间的有向边用来表示两个结点之间存在的偏序或前趋关系。

【操作系统】知识梳理(二)进程的描述与控制_第1张图片

前趋关系: P1→P2、 P1→P3、P1→P4、P2→P5、P3→P5、P4→P6、P5→P7、P6→P7。

2.1.2 程序的顺序执行

程序的顺序执行具有下列特征:
(1)顺序性。处理机严格按照程序所规定的顺序执行。
(2)封闭性。程序在执行时独占系统的全部资源,因此,系统资源状态的改变只与执行的程序有关,而不受外界因素的影响。
(3)可再现性。只要初始条件相同,一个程序的多次重复执行将得到相同的结果。

2.1.3 程序的并发执行

(1)间断性。由于资源共享和相互合作,并发执行的程序间形成了相互制约关系,导致程序的运行过程出现“执行一暂停一执行” 的现象。
(2) 失去封闭性。程序在执行时与其他并发执行的程序共享系统的资源,因此,资源状态的改变还与其他程序有关,即程序本身的执行环境要受到外界程序的影响。
(3)不可再现性。同样的初始条件,--个程序的多次重复执行可能会得到不同的结果。

2.1.4 进程的定义与特征

至今,进程仍没有一个统一的定 义,下面是几个较为典型的进程定义。
(1)进程是程序的一次执行。
(2)进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
(3)进程是具有独立功能的程序在-一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。

进程具有以下特征:
(1)动态性。进程是程序的一-次执行过程,因此是动态的。进程的动态性还表现在进程具有一定的生命期,它必须由创建而产生、由调度而执行、由撤消而消亡。动态性是进程的一个最基本的特征。
(2)并发性。并发性是指多个进程实体同存于内存中,且能在-段时间内同时执行。只有为程序创建进程后,多个程序才能正确地并发执行。并发是引入进程的目的,也是进程的另一个最基本的特征。
(3)独立性。进程实体是一个能够独立运行、独立分配资源和独立接受调度的基本单位。
(4)异步性。进程可按各自独立的、不可预知的速度向前推进。虽然进程具有异步性,但操作系统必须保证进程并发执行的结果是可再现的。

2.1.5 进程的状态

1)进程的基本状态
运行中的进程可能具有以下三种基本状态:
(1) 就绪状态。进程已获得除CPU以外的所有必要资源,只要得到CPU, 便可立即执行。
(2)执行状态。进程已得到CPU,其程序正在CPU.上执行。
(3)阻塞状态。正在执行的进程因某种事件(如I/O请求)的发生而暂时无法继续执行,只有等相应事件完成后,才能去竞争CPU。

【操作系统】知识梳理(二)进程的描述与控制_第2张图片
 

2)进程的挂起状态
在不少系统中,进程只有上述三种基本状态,但在另一些系统中,又增加了一些新的状态,最重要的是挂起状态。
“挂起”的实质是使进程不能继续执行,即使挂起后的进程处于就绪状态,它也不能活动状态。而且,处于静止状态的进程,只有通过“激活”动作,才能转换成活动状态。


【操作系统】知识梳理(二)进程的描述与控制_第3张图片

2.1.6 进程控制块(PCB) 

PCB的作用是将程序变成可并发执行的进程。
进程控制块中通常包含下列信息:
(1)进程标识符。进程标识符用于唯一地标识系统中的每个进程, 另外,还可以用父进程的标识符、子进程的标识符来描述进程的家族关系。
(2)处理机状态。处理机状态信息主要由处理机中各种寄存器的内容组成,它用于CPU切换时保存现场信息和恢复现场信息。
(3)进程调度信息。进程调度信息主要包括进程状态、优先级、等待和使用CPU的时间总和等信息,用作进程调度和对换的依据。
(4)进程控制信息。进程控制信息用于进程的控制,具体包括程序和数据的地址、进程同步和通信信息、资源清单和进程队列指针等。

2.2 进程控制

 2.2.1.操作系统内核

为了使操作系统内核代码和数据不会遭受到用户程序的破坏,通常将处理机的执行状态分为系统态和用户态两种不同状态:
(1) 系统态,也叫管态或内核态,它具有较高的特权,能执行- -切指令,访问所有寄存器和存储区。
(2)用户态,也叫目态,是-种具有较低特权的执行状态,它只能执行规定的指令,访问规定的寄存器和存储区。
通常,操作系统内核运行在系统态,而用户程序则都是运行在用户态。
原语是指由若干条指令组成、用来实现某个特定操作的一一个过程。原语的执行具有原子性,即原语在执行过程中不允许被中断。原语常驻内存,且在系统态下执行。

2.2.2.进程的创建

导致一个进程去创建另一个进程的典型事件有分时系统中的用户登录和批处理系统中的作业调度。另外,应用程序本身也可以根据需要去创建新的进程。
创建新进程是通过创建原语完成的,被创建的进程称作子进程,而创建子进程的进程则称作父进程。子进程又可以创建自己的子进程,从而形成一棵有向的进程树,即进程图。
进程创建原语的主要任务是创建进程控制块PCB。具体操作过程是:先从PCB集合中申请一个空闲的PCB,再为新进程分配内存等资源,并根据父进程提供的参数和分配到的资源情况来对PCB进行初始化,最后将新进程插入就绪队列。

2.2.3.进程的终止

当进程完成任务或遇到异常情况和外界干预需要结束时,应通过进程终止原语来终止进程。终止进程的实质是收回PCB。具体操作过程是:找到要终止进程的PCB;若该进程正在执行,则终止它的执行,并设置重新调度标志;终止属于该进程的所有子孙进程;释放终止进程所拥有的全部资源;将终止进程移出它所在的队列并收回PCB。

2.2.4.进程的阻塞和唤醒

当正在执行的进程需要等待某种事件的完成或本身无新工作可做时,应调用阻塞原语将自已从执行状态转换成阻塞状态。具体的操作过程是:停止进程的执行,将其状态改为阻塞状态,并把它的PCB插入相应的阻塞队列,转调度程序重新调度。当阻塞进程所等待的事件完成时,应调用唤醒原语将该进程的状态从阻塞状态转换成就绪状态。具体的操作过程是:在阻塞队列中移出该进程的PCB,将其设置成就绪状态,并把它插入就绪队列。

2.2.5.进程的挂起与激活

系统可利用挂起原语将一指定的进 程挂起。具体的操作过程是:若进程处于活动阻塞状态,则将它的状态转换成静止阻塞状态;否则,将它转换成静止就绪状态;将PCB复制到指定的内存区域供用户或父进程考查;若挂起前进程正在执行,则转调度程序重新进行进程调度。如果挂起是为了对换,则在挂起进程时还必须将它换出到外存中。
系统可利用激活原语激活-指定进程。具体的操作过程是:若进程处于静止阻塞状态,则将它转换成活动阻塞状态,否则将它转换成活动就绪状态;若进程转换成活动就绪状态,而系统又采用抢占调度策略,则应检查该进程是否有权抢占CPU,若有则应进行进程调度。同样,如果挂起是为了对换,则在激活被挂起的进程时还必须将它调入内存。

2.3 进程同步

2.3.1 进程同步的基本概念

1)两种形式的制约关系
在多道程序的环境下,进程之间存在着以下两种形式的制约关系:
(1)间接相互制约。这种制约主要源于资源共享。例如,有两个进程A和B,如果在进程A提出打印请求时,系统已将打印机分配给进程B,则进程A将处于阻塞状态;等进程B将打印机释放后,才唤醒进程A。
(2)直接相互制约。这种制约主要源于进程合作。例如,有一输入进程D通过单缓冲向计算进程C提供数据。当该缓冲空时,计算进程C因不能获得所需数据而阻塞,当进程D把数据送入缓冲时,便将C唤醒;反之,当缓冲区满时,进程D因不能再向缓冲区中投放数据而阻塞,当进程C将缓冲内数据取走时应唤醒D。
2)临界资源和临界区
在计算机中有许多资源-次只能允许一个进程使用,如果多个进程同时使用这些资源,则有可能造成系统的混乱,这些资源被称作临界资源。如打印机,多个进程同时使用一台打印机,将使它们的输出结果交织在一起,难于区分;又如共享变量,多个进程同时使用一个共享变量,会使其结果具有不可再现性。
在每个进程中,访问临界资源的那段代码称作临界区。为了使多个进程能有效地共享临界资源,并使程序的执行具有可再现性,系统必须保证进程互斥地使用临界资源,即保证它们互斥地进入自己的临界区。因此,必须在临界区前加一-段代码,用来检查对应的临界资源是否正被其他进程访问,这段代码被称为进入区;相应地,在临界区后也要加一段称为退出区的代码,用于将临界区从正被访问的标志恢复为未被访问的标志。
3)同步机制应遵循的规则
用来实现互斥的同步机制必须遵循下述四条规则:
(1)空闲让进。临界资源空闲时,应允许一个请求进入临界区的进程立即进入自己的临界区,以便有效地利用资源。
(2)忙则等待。当临界资源正被访问时,其他要求进入临界区的进程必须等待,以保证对临界资源的互斥使用。
(3)有限等待。任何要求访问临界资源的进程应能在有限的时间内进入自己的临界区,以免“死等”。
(4)让权等待。不能进入临界区的进程应立即释放CPU,以免“忙等”。

2.3.2 信号量机制

1)整型信号量
一个整型信号量通常对应于一类临界资源,它是一个非负的共享整数,用来表示该类资源的数目,除了初始化外,它只能通过两个标准的原子操作wait( 也称作P)和signal(也称作V)来访问。其算法如下所示:
        wait(S){
                while (S<=0) ; /*do no-op*/
                S--;}
                signal(S){
                S++;}
整形信号量的wait操作表示申请一个资源,signal 操作表示释放-一个资源。整型信号量的主要问题是:只要s≤0,wait 操作就会不断地测试,因而,整型信号没有遵循“让权等待”的规则。
2)记录型信号量
记录型信号量中除了需要一个用于代表资源数目的整型变量value外,还增加了一个进程链表指针list,用于链接所有等待该资源的进程。其算法如下所示:

【操作系统】知识梳理(二)进程的描述与控制_第4张图片

在记录型信号量中,S->value 的初值表示系统中某类资源的数目,因而又称为资源信号量。每次对它进行wait操作意味着申请一个 单位的该类资源,signal 操作意味着归还一个单位的该类资源。当S->value>0 时,它的值表示系统中该类资源当前可用的数目;S->value≤0时,表示该类资源已分配完毕,其绝对值表示系统中因申请该类资源而阻塞在s->list队列上的进程数目。
记录型信号量的wait操作中,当S.value减1后,结果小于0时,表示系统中已无资源可供分配,因此进程调用block原语自我阻塞,其PCB被插入信号量的等待队列list中。可见,记录型信号量遵循了“让权等待”规则。

2.3.3 信号量的应用

1)利用信号量实现前趋关系
信号量可用来描述程序或语句之间的前趋关系。若P;是Pj的直接前趋,即P→P,则可设置一个初值为0的公用信号量S,并将signal(S)操作放在P;之后,而在Pj的前面插入wait(S)操作,以保证Pj在P完成之后才开始执行。
2)利用信号量实现互斥
为使多个进程能互斥地访问某个临界资源,只需为该资源设置一- 互斥信号量mutex,并将其初值置为1,然后将访问该资源的临界区置于wait(mutex)和 signal(mutex)之间。下面的算法描述了如何利用信号量实现进程PI和P2的互斥。【操作系统】知识梳理(二)进程的描述与控制_第5张图片

2.4 经典进程的同步问题

1.生产者——消费者问题


生产者——消费者问题是最著名的进程同步问题。它描述了一组生产者与一组消费者,它们共享一个有界缓冲池,生产者向池中投入产品,消费者从池中取得产品。
假定缓冲池中有n个缓冲区,每个缓冲区只能存放-“个类型为 item的产品,而所有的生产者和消费者是相互等效的,则需要为该问题设置三个信号量:互斥信号量mutex,用于实现对缓冲池的互斥访问,其初值为1;资源信号量empty,用来表示空闲缓冲区的数量,其初值为n;资源信号量full, 用来表示满缓冲区的数量,即缓冲池中可供消费的产品数量,其初值为0。empty 和full 用来同步生产者和消费者进程,即当缓冲池全空时,消费者进程必须等待;缓冲池全满时,生产者进程必须等待。具体的算法描述如下:

【操作系统】知识梳理(二)进程的描述与控制_第6张图片
 【操作系统】知识梳理(二)进程的描述与控制_第7张图片

 2.哲学家进餐问题

由Dijkstra提出并解决的哲学家进餐问题也是一个经典的同步问题。该问题描述5个哲学家以交替思考、进餐的方式生活,他们坐在一张圆桌旁, 桌子上有5个碗和5只筷子。
当一个哲学家思考时,他与相邻的两个哲学家不会相互影响;但当他进餐时,需同时获得最靠近他的、左右两只筷子,若其中一只筷子被相邻的哲学家拿走,他就必须等待,因此,他们相互制约。
该问题中,哲学家争用的临界资源是筷子,而且,每只筷子是不等效的,因此需为每只筷子分别设置一个初值为1的互斥信号量,具体的算法描述如下:
semaphore chopstick[5]={1,1,1,1,1};
而第i位哲学家的活动可描述为:

【操作系统】知识梳理(二)进程的描述与控制_第8张图片
 

上述解法虽然可以保证互斥地使用筷子,但可能造成死锁。假如5个哲学家同时拿起各自左边的筷子,便将出现循环等待的局面,发生死锁现象。具体解决办法有以下几种。
(1)至多只允许4个哲学家同时进餐。
(2)仅当哲学家左右两边的筷子都可用时,才允许他进餐。
(3)规定奇数号哲学家先拿左边的筷子,再拿右边的筷子:而偶数号哲学家则先拿右边的筷子,再拿左边的筷子。

3.读者——写者问题

一个数据对象,如文件或记录,能被多个进程共享,可把那些只要求读数据对象的进程称为“读者”,其他进程则称为“写者”。显然,多个读者可同时读-一个共享对象, 但不允许一个写者与读者同时访问共享对象,也不允许多个写者同时访问共享对象,否则会造成数据的不一致性。这个经典同步问题就是“读者——写者 问题”。
若考虑读者优先,即除非有写者正在写,否则读者就毋须等待,则该问题的算法可描述为:

【操作系统】知识梳理(二)进程的描述与控制_第9张图片
 

其中,变量readcount表示正在进行读的读者数目,由于每个读者都要对它进行访问并作修改,故readcount 是一个临界资源;互斥信号量readcount用来实现多个读者对readcount变量的互斥访问,其初值为1;互斥信号量mutex对应被共享的数据对象,用来实现写者之间以及写者与读者之间对该共享数据对象的互斥访问,其初值为1。由于只要有一个读者在读,其余读者便无需等待而可直接进行读操作,因此,仅readcounter=0,即尚无其他读者在读时,读者进程才需要执行wait(mutex)操作, 而写者必须与任意其他进程互斥,故每次写操作之前都必须进行wait(mutex)操作。

2.5 管程机制

1.管程的定义


管程利用共享数据结构抽象地表示系统中的共享资源,并且将对该共享数据结构实施的特定操作定义为一组过程。换句话说,管程是由一组局部的共享变量、对局部变量进行操作的一组过程以及对局部变量进行初始化的语句序列构成的一个软件模块,取名为monitor_ name 的管程,其语法描述如下:
【操作系统】知识梳理(二)进程的描述与控制_第10张图片

 管程具有以下的特点: 
(1)管程内的局部变量只能被局部于管程内的过程所访问,反之亦然,即局部于管程内的过程只能访问管程内的变量和形式参数。
(2)任何进程只能通过调用管程提供的过程入口进入管程。
(3) 任一时刻,最多只能有一个进程在管程中执行。
保证进程互斥地进入管程是由编译器负责的,也就是说,管程是一一种编程语言的构件,它的实现需要得到编译器的支持。

2.条件变量

在任何时刻,最多只有一个进程在管程中执行,因此用管程很容易实现互斥,只要将需要互斥访问的资源用数据结构来描述,并将该数据结构放入管程中便可。若要用管程来实现同步,则在相应条件不满足时(如临界资源得不到时)必须能够将在管程内执行的进程阻塞。由于阻塞的原因不同,为了将它们区分开,引入了局部于管程的条件变量。条件变量的定义格式为: conditionx,y; 对条件变量只能执行以下两种操作。
(1) wait 操作。如x.wait)用来将执行进程挂到与条件变量x相应的等待队列上。
(2) signal 操作。如x.signal()用来唤醒与x条件变量相应的等待队列上的一个进程。值得注意的是,若没有等待进程,则x.signal不起任何作用。

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

利用管程来解决生产者一消费者问题,首先必须为它们建立-一个管程,具体算法描述如下:

【操作系统】知识梳理(二)进程的描述与控制_第11张图片
 

 上述管程PC中包括两个局部过程: put 和get。过程put负责将产品投放到缓冲池中,过程get负责从缓冲池中取出产品。另外,整型变量count表示缓冲池中已存放的产品数目,条件变量notfull、 notempty分别对应于缓冲池不全满、缓冲池不全空两个条件。
相应的生产者和消费者的算法可描述为:

【操作系统】知识梳理(二)进程的描述与控制_第12张图片

【操作系统】知识梳理(二)进程的描述与控制_第13张图片 

2.6 进程通信

1.进程通信的类型

高级通信是指用户可直接利用操作系统所提供的一-组通信命令(原语),高效地传送大量数据的一种通信方式。它又被分为共享存储器系统、管道通信、消息传递系统以及客户机-服务器系统四大类。
(1)共享存储器系统。高级通信中的共享存储器系统是指进程之间通过对共享存储区的读写来交换数据。需要通信的进程在通信前,先向系统申请获得共享存储区中的一个分区,并将其附加到自己的地址空间中,便可对其中的数据进行正常的读、写,读写完成或不再需要该分区时,将其归还给共享存储区。共享存储器系统的另一种方式是利用共享的数据结构来进行进程通信,但这种方式对共享数据结构的设置及对进程间的同步,都必须由程序员来处理,且只能进行少量的数据交换,因此属于低级通信方式。
(2) 管道通信。所谓“管道”是指连接两个进程的一一个共享文件,发送进程以字符流的形式将大量的信息写入管道,接收进程则在需要时丛管道中读出数据。为了协调双方的通信,管道通信机制必须对发送进程和接收进程,在利用管道进行通信时实施同步和互斥,并只有在确定了对方存在时才能进行通信。
(3)消息传递系统。消息传递系统中,进程间的数据交换以格式化的消息(网络中称作报文)为单位。根据实现方式,它又可分为直接通信和间接通信两类。在直接通信方式中,源进程可直接将消息发送给目标进程,此类操作系统通常提供sendreceiver, message)和receive(sender, message)两条通信命令(原语)供用户使用。在间接通信方式中,进程间需要
通过某种中间实体,即信箱来进行通信,发送进程将消息投入信箱,而接收进程则从信箱中取得消息,因此,它不仅能实现实时通信,还能实现非实时通信,此类操作系统通常提供若干条原语分别用于信箱的创建、撤消和消息的发送和接收等。
(4)客户机-服务器系统。该通信机制已广泛应用于网络环境的各种应用领域,其实现方式主要有套接字、远程过程调用和远程方法调用三种类型。
①套接字。基于文件类型的套接字关联到-一个特殊的文件,同一台计算机上的通信双方,通过对这个特殊文件的读写来实现彼此之间的通信,其实现原理类似于管道。基于网络型的一个套接字就是一个通信标识类型的数据结构,它包含了通信目的地址、通信使用的端口号、通信网络的传输层协议、进程所在的网络地址,以及针对客户或服务器程序提供的不同系统调用(或API函数)等,是进程通信和网络通信的基本构件。一对通 过网络通信的进程被分配了一对套接字,一个属于接收进程(或服务器端),一个属于发送进程(或客户端)。一般地,客户端发出连接请求时,会随机申请一一个套接字,并被主机赋予一一个端口,与该套接字绑定;服务器端通常拥有全局公认的套接字和指定端口(如ftp服务器监听端口为21,Web或http服务器监听端口为80),并通过监听端口等待客户请求,一旦收到请求,就接受来自客户端的连接,从而完成连接;根据套接字中的端口,主机间传输的数据可以准确地分送到相应的进程:当通信结束时,服务器端关闭与客户端相连的套接字,从而撤销连接。
②远程过程调用和远程方法调用。远程过程(函数)调用RPC(Remote Procedure Call)是一个通信协议,用于通过网络连接的系统。该协议允许运行于- - 台主机(本地)系统上的进程调用另一台主机(远程)系统上的过程,就如同调用本地过程一样。 如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程方法调用。通常,对于每个能够独立运行的远程过程在客户端和服务器端都有一一个存根(stub),当本地进程调用某个远程过程时,实际是调用与该过程关联的存根,它将本地进程提供的远程过程调用参数等信息构建成一个消息,由本地客户进程通过网络传递给远程服务器进程;服务器的存根接收到这一消息后,拆开消息获得过程调用的参数,并以- -般方式调用服务器上对应的远程过程,最后将结果消息打包发回客户端。

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

消息缓冲队列通信机制通过内存中公用的消息缓冲区进行进程通信,属于直接通信方式。发送进程发送消息时,需申请一个消息缓冲区,并把自己的进程标识符和有关消息的内容填入消息缓冲区,然后将该消息缓冲区插入到接收进程的消息缓冲队列中;接收进程接收消息时,需从自己的消息缓冲队列中摘下一个消息缓冲区,取出其中的消息,然后把消息缓冲区归还给系统。
1)消息缓冲队列通信机制中的数据结构
消息缓冲队列通信机制中,最重要的数据结构是消息缓冲区,它可描述为:

【操作系统】知识梳理(二)进程的描述与控制_第14张图片【操作系统】知识梳理(二)进程的描述与控制_第15张图片

2)发送原语
发送原语中,参数receiver为接收进程的标识符,a为发送进程存放消息的内存空间(即发送区)的地址。发送原语可描述如下:

【操作系统】知识梳理(二)进程的描述与控制_第16张图片
 

3)接收原语
接收原语中,参数b为接收进程用来存放消息的内存空间(即接收区)的地址。接收原语可描述如下:

【操作系统】知识梳理(二)进程的描述与控制_第17张图片

2.7 线程

1.线程的基本概念 

线程的概念是在20世纪80年代中期提出的,它的引入目的是为了减少程序在并发执.行时所付出的时空开销,从而使OS具有更好的并发性。在多线程OS中,将拥有资源的基本单位与调度和分派的基本单位分开处理,此时,一个进程中含有一个或多个相对独立的线程,进程只是拥有资源的基本单位,而不再是一一个可执行的实体;每个线程都是一个可执行的实体,即CPU调度和分派的基本单位是线程。
线程由线程标识符、程序计数器、一组寄存器的值和堆栈组成,除了上述在运行中必不可少的资源外,线程基本.上不拥有系统的资源,但它可以和属于同一个进程的其他线程共享进程所拥有的全部资源,如进程的代码段、数据段、已打开的文件、定时器和信号量机构等。每个线程都是一一个可执行的实体,不同进程中的多个线程以及同一个进程内的多个线程均可以并发地执行。由于线程基本不拥有资源,因此,创建线程时不需要另行分配资源、终止时也不需要进行资源的回收,而切换时也大大减少了需保存和恢复的现场信息,因此,线程的创建、终止和切换都要比进程迅速且开销小。由于同-进程内的各个线程可以共享该进程所占用的内存空间和打开的文件,因此,这些线程间的通信也非常简便和迅速。

2.线程的控制

在多线程OS环境下,应用程序在启动时,OS将为它创建一一个进程,同时为该进程创建第一个线程。以后在线程的运行过程中,它可根据需要利用线程创建函数(或系统调用)再去创建若千个线程。所以线程是由线程创建的,但线程间并不提供父子关系的支持。
每个线程被创建后,便可与其他线程一起并发地运行。如同传统的进程一样, 并发运行的线程之间也存在着共享资源和相互合作的制约关系,致使线程在运行时也具有间断性。相应地,线程在运行时,也具有执行、就绪和阻塞三种基本状态,并随着自身的运行和外界环境的变换而不断地在三种状态之间转换。
当线程完成了自己的工作后,它便可正常终止。线程的终止也可能是因为运行中出现错误或其他原因而引起的,此时它是被强行终止的。但有些线程(主要是系统线程),它们旦被建立起来之后,便会一直运行下去而不被终止。

3.内核支持线程和用户线程

线程已在许多系统中实现,但实现的方式并不完全相同。有些系统中,特别是一些数据库管理系统如informix中,所实现的是用户级线程:而另一些系统(如Macintosh和OS/2)所实现的是内核支持线程;还有一- 些系统如Solaris,则同时实现了这两种不同类型的线程。
(1)用户级线程。用户级线程仅存在于用户空间中,而与内核无关。就内核而言,它只是管理常规的进程一即 单线程进程,感知不到用户级线程的存在。每个线程的控制块都设置在用户空间中,所有对线程的操作也在用户空间中由线程库中的函数(过程)完成,而无需内核的帮助。用户级线程的优点是不需要得到内核的支持:而且,线程的切换毋须陷入内核,故切换开销小、速度非常快。另外,线程库对用户线程的调度算法与OS的调度算法无关,因此,线程库可提供多种调度算法供应用程序选择使用。但在纯用户级线程的系统中,对应用程序来讲,当一个线程因为执行系统调用而阻塞时,将导致对应进程中所有线程的阻塞;另外,用户级线程无法享用多处理机系统中多个处理器带来的好处。
(2)内核支持线程。内核支持线程是在核心空间实现的。内核为每个线程在核心空间中设置了一个线程控制块,用来登记该线程的线程标识符、寄存器值、状态、优先级等信息。所有对线程的操作,如创建、撤消和切换等,都是通过系统功能调用由内核中的相应处理程序完成的。内核支持线程克服了用户级线程的两个缺点,首先内核可以把同一个进程中的多个线程调度到多个处理器中;其次,如果进程中的一个线程被阻塞,内核可以调度同一个进程中的另一个线程。它的另一个优点是内核本身也可以使用多线程的方式来实现。它的主要缺点是即使CPU在同一个进程内的多个线程之间切换,也需要陷入内核,因此,其速度和效率不如用户级线程。
(3)组合方式。为了同时获得用户级线程和内核支持线程的便利,有些OS把用户级线程和内核支持线程两种方式进行组合,内核提供对内核支持线程的建立、调度和管理的支持,同时,也允许用户应用程序建立、调度和管理用户级线程。通过时分多路复用技术,用户级线程可连接到一些内核支持线程上,具体的连接方式如图2.4所示,有一对一、多对一和多对多三种方式。采用这种方式,编程人员可以根据需要灵活地决定需多少个内核支持线程与自己的用户级线程多路复用,以达到满意的效果。

【操作系统】知识梳理(二)进程的描述与控制_第18张图片 

你可能感兴趣的:(操作系统,线程与进程)