第3章进程管理 在计算机操作系统中,进程是资源分配的基本单位,同时进程也可作为独立运行的基本单 位,用户可以从进程观点来研究操作系统。显然,进程这一概念在操作系统中极为重要。本章 讨论进程的基本概念、进程控制、进程互斥与同步、进程通信及相关题解。 3.1内容辅导 3.1.1进程的基本概念 1.程序的顺序执行 个程序通常由若干个程序段所组成,它们必须按照某种先后次序来执行,仅当前一个操 作执行完后才能执行后继操作,这类计算过程就是程序的顺序执行过程。程序顺序执行时有如 下特征 (1)顺序性:处理机的操作严格按照程序所规定的顺序执行,即每一操作必须在下一操作 开始之前结束 (2)封闭性:程序运行时独占系统的各种资源,故这些资源的状态(除初始状态外)只有本 程序才能改变。程序一旦开始运行,其执行结果不受外界因素影响 (3)可再现性:只要程序执行时的初始条件和执行环境相同,当程序重复执行时,都将获得 相同的结果。 2.程序的并发执行 所谓程序的并发执行是指若干个程序〈或程序段〉同时在系统中运行,这些程序(或程序 段)的执行在时间上是重叠的,一个程序(或程序段)的执行尚未结束,另一个程序,(或程序段) 的执行已经开始。 程序的并发执行虽然提高了系统吞吐量,但也产生了下述一些与顺序执行不同的新特征 (1)制约性:程序在并发执行时,由于它们共享资源或为完成同一项任务而相互合作 致使并发程序之间形成了相互制约关系。制约关系有两种: ①直接制约关系=进程一进程 ②间接制约关系z进程一资源一进程 (2)失去封闭性:程序在并发执行时,多个程序共享系统中的各种资源,因而这些资源的 状态将由多个程序来改变,致使程序的运行失去封闭性 (3)不可再现性:程序并发执行时,由于失去了封闭性,也将导致失去其可再现性 3.进程的定义及特征 进程是操作系统中最基本、最重要的概念,但直至目前还没有一个统一的定义,这里给出 几种比较容易理解又能反映进程实质的定义 (1)进程是程序的一次执行。 (2)进程是可以和别的计算并发执行的计算。 (3)进程是程序在一个数据集合上运行的过程,是系统进行资源分配和调度的一个独立单 位 (4)进程是一个具有一定功能的程序关于某个数据集合的一次运行活动。 以上进程的定义,尽管各有侧重,但它们在本质上是相同的 进程具有以下几个基本特征 (1)动态性:进程是程序的一次执行过程,因而是动态的。动态特性还表现在它因创建 而产生,由调度而执行,因得不到资源而暂停执行,最后由撤消而消亡 (2)并发性:引入进程的目的就是为了使程序能与其他程序并发执行,以提高资源利用率 (3)独立性:进程是一个能独立运行的基本单位,也是系统进行资源分配和调度的独立单
第 3 章 进程管理 在计算机操作系统中,进程是资源分配的基本单位,同时进程也可作为独立运行的基本单 位,用户可以从进程观点来研究操作系统。显然,进程这一概念在操作系统中极为重要。本章 讨论进程的基本概念、进程控制、进程互斥与同步、进程通信及相关题解。 3.1 内容辅导 3.1.1 进程的基本概念 1.程序的顺序执行 一个程序通常由若干个程序段所组成,它们必须按照某种先后次序来执行,仅当前一个操 作执行完后才能执行后继操作,这类计算过程就是程序的顺序执行过程。程序顺序执行时有如 下特征: (1)顺序性:处理机的操作严格按照程序所规定的顺序执行,即每一操作必须在下一操作 开始之前结束。 (2)封闭性: 程序运行时独占系统的各种资源,故这些资源的状态(除初始状态外)只有本 程序才能改变。程序一旦开始运行,其执行结果不受外界因素影响。 (3)可再现性:只要程序执行时的初始条件和执行环境相同,当程序重复执行时,都将获得 相同的结果。 2.程序的并发执行 所谓程序的并发执行是指若干个程序〈或程序段〉同时在系统中运行,这些程序(或程序 段)的执行在时间上是重叠的,一个程序(或程序段)的执行尚未结束,另一个程序,(或程序段) 的执行已经开始。 程序的并发执行虽然提高了系统吞吐量,但也产生了下述一些与顺序执行不同的新特征: (1) 制约性:程序在并发执行时,由于它们共享资源或为完成同一项任务而相互合作, 致使并发程序之间形成了相互制约关系。制约关系有两种: ①直接制约关系=进程一进程。 ②间接制约关系 z 进程一资源一进程。 (2)失去封闭性:程序在并发执行时,多个程序共享系统中的各种资源,因而这些资源的 状态将由多个程序来改变,致使程序的运行失去封闭性。 (3)不可再现性:程序并发执行时,由于失去了封闭性,也将导致失去其可再现性。 3. 进程的定义及特征 进程是操作系统中最基本、最重要的概念,但直至目前还没有一个统一的定义,这里给出 几种比较容易理解又能反映进程实质的定义: (1)进程是程序的一次执行。 (2)进程是可以和别的计算并发执行的计算。 (3)进程是程序在一个数据集合上运行的过程,是系统进行资源分配和调度的一个独立单 位。 (4)进程是一个具有一定功能的程序关于某个数据集合的一次运行活动。 以上进程的定义,尽管各有侧重,但它们在本质上是相同的。 进程具有以下几个基本特征: (1)动态性:进程是程序的一次执行过程,因而是动态的。动态特性还表现在它因创建 而产生,由调度而执行,因得不到资源而暂停执行,最后由撤消而消亡。 (2)并发性:引入进程的目的就是为了使程序能与其他程序并发执行,以提高资源利用率。 (3)独立性:进程是一个能独立运行的基本单位,也是系统进行资源分配和调度的独立单
(4)异步性:进程以各自独立的、不可预知的速度向前推进 (5)结构特征:为了描述和记录进程的运动变化过程,并使之能正确运行,应为每个进程配 置一个进程控制块。这样,从结构上看,每个进程都由程序段、数据段和进程控制块三部分组 4.进程状态及其变化 进程执行时的间断性,决定了进程可能具有多种状态。事实上,运行中的进程至少具有以 下三种基本状态。 (1)就绪状态进程已获得除处理机以外的所有资源,一旦分到了处理机就可以立即执 行,这时进程所处的状态为就绪状态 2)执行状态执行状态又称运行状态。当一个进程获得必要的资源.并占有处理机,即 在处理机上运行,此时进程所处的状态为执行状态。 (3)阻塞状态阻塞状态又称等待状态。正在执行的进程,由于发生某事件而暂时无法执 行下去(如等待输入/输出完成〉,此时进程所处的状态为阻塞状态 进程并非固定处于某一状态,它随着自身的推进和外界条件的变化而发生变化 5.进程的表示 进程通常有三部分组成:程序数据集合和进程控制块。 (1)程序:描述了进程所要完成的功能 (2)数据集合:程序执行时所需要的数据和工作区。 (3)进程控制块:为了描述和控制进程的运行,系统为每个进程定义了一个数据结构一进 程控制块(PCB)。所谓系统创建一个进程,就是由系统为某个程序(包含数据段)设置一个PCB, 用于对该进程进行控制和管理。进程执行完成时,由系统收回其PCB,该进程便消亡了。系统 将根据PCB而感知进程的存在,故PCB是进程存在的惟一标志 一般来说,根据操作系统的要求不同,进程PCB所包含的内容多少会有些不同,但通常包 括下面所列的内容:进程标识符,进程当前状态,进程队列指针,程序开始地址,迸程优先 级,CP现场保护区,通信信息,家族联系,占有资源清单等。 在一个系统中,通常存在许多进程,为了对它们进行有效管理,应该用适当方法将PCB组 织起来。目前常用链表或表格将PCB组织起来。 3.1.2进程控制 进程控制的职责是对系统中的全部进程实施有效的管理。其功能包括进程的创建、进 程的撤消、进程的阻塞与唤醒等。这些功能一般是由操作系统的内核来实现的。 操作系统的内核是基于硬件的第一次软件扩充。在现代操作系统设计中,往往把一些与硬 件紧密相关的模块或运行频率较高的模块以及为许多模块所公用的一些基本操作安排在靠近 硬件的软件层次中,并使它们常驻内存,以提高操作系统的运行效率 进程控制功能是通过执行各种原语来实现的。所谓原语是由若干条机器指令构成的,用于 完成某一特定功能的一段程序。原语在执行期间不可分割,所以原语操作具有原子性 为了防止操作系统及关键数据如PCB等受到用户程序有意或无意的破坏,通常将处理机 的执行状态分成两种:核心态与用户态 ●核心态又称管态:是操作系统管理程序执行时机器所处的状态。它具有较高的特权, 能执行一切指令,访问所有的寄存器和存储区 用户态又称目态:是用户程序执行时机器所处的状态。这是具有较低特权的执行状态 它只能执行规定的指令,访问指定的寄存器和存储区 1.进程创建
位。 (4)异步性:进程以各自独立的、不可预知的速度向前推进。 (5)结构特征:为了描述和记录进程的运动变化过程,并使之能正确运行,应为每个进程配 置一个进程控制块。这样,从结构上看,每个进程都由程序段、数据段和进程控制块三部分组 成。 4. 进程状态及其变化 进程执行时的间断性,决定了进程可能具有多种状态。事实上,运行中的进程至少具有以 下三种基本状态。 (1)就绪状态 进程已获得除处理机以外的所有资源,一旦分到了处理机就可以立即执 行,这时进程所处的状态为就绪状态。 (2)执行状态 执行状态又称运行状态。当一个进程获得必要的资源.并占有处理机,即 在处理机上运行,此时进程所处的状态为执行状态。 (3)阻塞状态 阻塞状态又称等待状态。正在执行的进程,由于发生某事件而暂时无法执 行下去(如等待输入/输出完成〉,此时进程所处的状态为阻塞状态。 进程并非固定处于某一状态,它随着自身的推进和外界条件的变化而发生变化。 5.进程的表示 进程通常有三部分组成:程序数据集合和进程控制块。 (1)程序 :描述了进程所要完成的功能。 (2)数据集合:程序执行时所需要的数据和工作区。 (3)进程控制块:为了描述和控制进程的运行,系统为每个进程定义了一个数据结构—进 程控制块(PCB)。所谓系统创建一个进程,就是由系统为某个程序(包含数据段)设置一个 PCB, 用于对该进程进行控制和管理。进程执行完成时,由系统收回其 PCB,该进程便消亡了。系统 将根据 PCB 而感知进程的存在,故 PCB 是进程存在的惟一标志。 一般来说,根据操作系统的要求不同,进程 PCB 所包含的内容多少会有些不同,但通常包 括下面所列的内容:进程标识符,进程当前状态,进程队列指针,程序开始地址,迸程优先 级,CPU 现场保护区,通信信息,家族联系,占有资源清单等。 在一个系统中,通常存在许多进程,为了对它们进行有效管理,应该用适当方法将 PCB 组 织起来。目前常用链表或表格将 PCB 组织起来。 3.1.2 进程控制 进程控制的职责是对系统中的全部进程实施有效的管理。其功能包括进程的创建、进 程的撤消、进程的阻塞与唤醒等。这些功能一般是由操作系统的内核来实现的。 操作系统的内核是基于硬件的第一次软件扩充。在现代操作系统设计中,往往把一些与硬 件紧密相关的模块或运行频率较高的模块以及为许多模块所公用的一些基本操作安排在靠近 硬件的软件层次中,并使它们常驻内存,以提高操作系统的运行效率。 进程控制功能是通过执行各种原语来实现的。所谓原语是由若干条机器指令构成的,用于 完成某一特定功能的一段程序。原语在执行期间不可分割,所以原语操作具有原子性。 为了防止操作系统及关键数据如 PCB 等受到用户程序有意或无意的破坏,通常将处理机 的执行状态分成两种:核心态与用户态。 ⚫ 核心态又称管态:是操作系统管理程序执行时机器所处的状态。它具有较高的特权, 能执行一切指令,访问所有的寄存器和存储区。 ⚫ 用户态又称目态:是用户程序执行时机器所处的状态。这是具有较低特权的执行状态, 它只能执行规定的指令,访问指定的寄存器和存储区。 1.进程创建
进程创建是由创建原语实现的。当需要进程时,就可以建立一个新进程。被创建的进程称 为子进程,建立进程的进程称为父进程。 创建原语的主要功能是为被创建进程形成一个PCB,并填入相应的初始值。其主要操作过 程是先向系统申请一个空闲PCB结构,再根据父进程所提供的参数将子进程的PB初始化,并 将此PCB插入就绪队列,最后返回一个进程的标识号。 2.进程撤消 进程撤消是由撤消原语实现的。一个进程在完成其任务后,应予以撤消,以便及时释放它 所占用的各类资源。撤消原语可采用两种撤消策略:一种策略是只撤消一个具有指定标识符的 进程,另一种策略是撤消指定进程及其子孙进程 撤消原语的主要功能是收回被撤消进程占用的所有资源,并撤消它的PCB。其主要操作过 程是先从PCB集合中找到被撤消进程的PCB,若被撤消进程正处于运行状态,则应立即停止该 进程的执行,设置重新调度标志,以便进程撤消后将处理机分给其他进程。对后一种撤消策略, 若被撤消进程有子孙进程,还应将该进程的子孙进程予以撤消。对于被撤消进程所占有的资源, 或者归还给父进程,或者归还给系统。最后撤消它的PCB。 3.进程阻塞与唤醒 阻塞原语的作用是将进程由执行状态转为阻塞状态,而唤醒原语的作用则是将进程由阻 塞状态变为就绪状态。 当一个进程期待的某一事件尚未出现时,该进程调用阻塞原语将自己阻塞起来。阻塞原语 在阻塞一个进程时,由于该进程正处于执行状态,故应先中断处理机和保存该进程的CPU现场 然后将该进程插入到等待该事件的等待队列中。再从就绪队列中选择一个新的进程投入运行。 对处于阻塞状态的进程,当该进程期待的事件出现时,由发现者进程调用唤醒原语将阻塞 的进程唤醒,使其进入就绪状态。 应当注意,一个进程由执行状态转变为阻塞状态,是这个进程自己调用阻塞原语去完成的 而进程由阻塞状态到就绪状态,是另一个发现者进程调用唤醒原语实现的,一般这个发现者进 程与被唤醒进程是合作的并发进程。 3.1.3进程同步 多道程序系统中进程是并发执行的,这些进程之间存在着不同的相互制约关系,为了协调 进程之间的相互制约关系,就需要实现进程的同步。互斥是同步的一种特殊情况。 1.进程同步的基本概念 (1)临界资源和临界区:系统中的多个进程可以共享系统中的各种资源,然而其中许多资 源一次只能为一个进程所使用。我们把一次仅允许一个进程使用的资源称为临界资源。许多 物理设备都属于临界资源,如打印机、绘图机等。除物理设备外,还有许多变量、数据等都可 由若干进程所共享,它们也属于临界资源。在每个进程中,访问临界资源的那段程序称为临界 (2)同步:一个进程到达了某些点后,除非另一进程己完成了某些操作,否则就不得不停下 来等待这些操作的结束,这就是进程间的同步 (3)互斥:两个或两个以上进程,由于不能同时使用同一临界资源,只能一个进程使用完了 另一个进程才能使用,这种现象称为进程互斥 为禁止两个进程同时进入临界区,可采用软件解决方法或一个同步机构来协调它们。但是, 不论是软件算法或同步机构都应遵循下述准则:①空闲让进;②忙则等待:③有限等待;④ 让权等待。 2.信号量和P、V操作 个信号量的建立必须经过说明,即应该准确说明s的意义和初值。每个信号量都有相应 的一个队列,在建立信号量时,队列为空。P、Ⅴ操作为两条原语,信号量的值仅能由P、V操作
进程创建是由创建原语实现的。当需要进程时,就可以建立一个新进程。被创建的进程称 为子进程,建立进程的进程称为父进程。 创建原语的主要功能是为被创建进程形成一个 PCB,并填入相应的初始值。其主要操作过 程是先向系统申请一个空闲 PCB 结构,再根据父进程所提供的参数将子进程的 PCB 初始化,并 将此 PCB 插入就绪队列,最后返回一个进程的标识号。 2. 进程撤消 进程撤消是由撤消原语实现的。一个进程在完成其任务后,应予以撤消,以便及时释放它 所占用的各类资源。撤消原语可采用两种撤消策略:一种策略是只撤消一个具有指定标识符的 进程,另一种策略是撤消指定进程及其子孙进程。 撤消原语的主要功能是收回被撤消进程占用的所有资源,并撤消它的 PCB。其主要操作过 程是先从 PCB 集合中找到被撤消进程的 PCB,若被撤消进程正处于运行状态,则应立即停止该 进程的执行,设置重新调度标志,以便进程撤消后将处理机分给其他进程。对后一种撤消策略, 若被撤消进程有子孙进程,还应将该进程的子孙进程予以撤消。对于被撤消进程所占有的资源, 或者归还给父进程,或者归还给系统。最后撤消它的 PCB。 3.进程阻塞与唤醒 阻塞原语的作用是将进程由执行状态转为阻塞状态,而唤醒原语的作用则是将进程由阻 塞状态变为就绪状态。 当一个进程期待的某一事件尚未出现时,该进程调用阻塞原语将自己阻塞起来。阻塞原语 在阻塞一个进程时,由于该进程正处于执行状态,故应先中断处理机和保存该进程的 CPU 现场, 然后将该进程插入到等待该事件的等待队列中。再从就绪队列中选择一个新的进程投入运行。 对处于阻塞状态的进程,当该进程期待的事件出现时,由发现者进程调用唤醒原语将阻塞 的进程唤醒,使其进入就绪状态。 应当注意,一个进程由执行状态转变为阻塞状态,是这个进程自己调用阻塞原语去完成的, 而进程由阻塞状态到就绪状态,是另一个发现者进程调用唤醒原语实现的,一般这个发现者进 程与被唤醒进程是合作的并发进程。 3.1.3 进程同步 多道程序系统中进程是并发执行的,这些进程之间存在着不同的相互制约关系,为了协调 进程之间的相互制约关系,就需要实现进程的同步。互斥是同步的一种特殊情况。 1.进程同步的基本概念 (1)临界资源和临界区:系统中的多个进程可以共享系统中的各种资源,然而其中许多资 源一次只能为一个进程所使用。我们把一次仅允许一个进程使用的资源称为临界资源。许多 物理设备都属于临界资源,如打印机、绘图机等。除物理设备外,还有许多变量、数据等都可 由若干进程所共享,它们也属于临界资源。在每个进程中,访问临界资源的那段程序称为临界 区。 (2)同步:一个进程到达了某些点后,除非另一进程已完成了某些操作,否则就不得不停下 来等待这些操作的结束,这就是进程间的同步。 (3)互斥:两个或两个以上进程,由于不能同时使用同一临界资源,只能一个进程使用完了, 另一个进程才能使用,这种现象称为进程互斥。 为禁止两个进程同时进入临界区,可采用软件解决方法或一个同步机构来协调它们。但是, 不论是软件算法或同步机构都应遵循下述准则: ①空闲让进;②忙则等待;③有限等待;④ 让权等待。 2.信号量和 P、V 操作 一个信号量的建立必须经过说明,即应该准确说明 s 的意义和初值。每个信号量都有相应 的一个队列,在建立信号量时,队列为空。P、V 操作为两条原语,信号量的值仅能由 P、V 操作
原语来改变。 P、V操作的定义如下: P(s):s=s-1 若S>=0,则进程继续运行。 若S0,则进程继续执行。 若S<=0,则从信号量等待队列中移出第一个进程,使其变为就绪状态,然后再返回原 进程继续执行 3.信号量的应用 利用信号量可以解决进程间的同步和互斥问题,实现进程间的互斥和同步模型如下 1)互斥模型 进程Pl 进程P2 P(S) 其中,信号量的初值:S=1;CS1,CS2分别是进程P1和P2的临界区 (2)同步模型 进程P1 进程P2 LI: P(S 其中,信号量的初值:S=0。 (3)用P、V操作描述前趋关系 若干进程为了完成一个共同任务而并发执行。然而,这些并发进程之间根据逻辑上的需 要,有的操作可以没有时间上的先后次序,即不论谁先做,最后的计算结果都是正确的。但有的 操作有一定的先后次序,也就是说它们必须遵循一定的同步规则,只有这样,并发执行的最后 结果才是正确的。我们可以用本章前面介绍的前趋图来描述进程在执行次序上的先后关系 (4)生产者·消费者问题 生产者-消费者问题是最著名的进程同步问题。它描述了一组生产者向一组消费者提供产 品,它们共享一个有界缓冲区,生产者向其中投放产品,消费者从中取得产品。生产者消费者问 题是许多相互合作进程的一种抽象。例如,在输入时,输入进程是生产者,计算进程是消费者 在输出时,计算进程是生产者,打印进程是消费者。因此,该问题具有很大实用价值。 我们把一个长度为n的有界缓冲区(n)0)与一群生产者进程P1、P2、…、P和一群消费 者进程CI、C2、…、CK联系起来。假定这些生产者和消费者是互相等效的。只要缓冲区未满, 生产者就可以把产品送入缓冲区,类似地,只要缓冲区未空,消费者便可以从缓冲区中取走物 品并消耗它。生产者和消费者的同步关系将禁止生产者向满的缓冲区输送产品,也禁止消费者 从空的缓冲区中提取物品 为解决这一类生产者-消费者问题,应该设置两个同步信号量,一个说明空缓冲单元的数 用 empty表示,其初值为有界缓冲区的大小n,另一个说明满缓冲单元的数目,用fu11表示, 其初值为0。在本例中有P1、P2、…、Pm个生产者和C1、C2、…、CK个消费者,它们在执行 生产活动和消费活动中要对有界缓冲区进行操作。由于有界缓冲区是一个临界资源,必须互斥 使用,所以,另外还需设置一个互斥信号量 mutex,其初值为1。生产者.消费者问题的同步描述 如下 int full /*申满缓冲单元的数目* int empty=n /*空缓冲单元的数目*/
原语来改变。 P、V 操作的定义如下: P(s): s=s-1 若 S>=0,则进程继续运行。 若 S0,则进程继续执行。 若 S<=0,则从信号量等待队列中移出第一个进程,使其变为就绪状态,然后再返回原 进程继续执行。 3.信号量的应用 利用信号量可以解决进程间的同步和互斥问题,实现进程间的互斥和同步模型如下: (1)互斥模型 进程 P1 进程 P2 P(S) P(S) CS1 CS2 V(s) v(s) 其中,信号量的初值:S=1;CS1,CS2 分别是进程 P1 和 P2 的临界区。 (2)同步模型 进程 P1 进程 P2 L1:P(S) L2: V(S) 其中,信号量的初值:S=0。 (3)用 P、V 操作描述前趋关系 若干进程为了完成一个共同任务而并发执行。然而,这些并发进程之间根据逻辑上的需 要,有的操作可以没有时间上的先后次序,即不论谁先做,最后的计算结果都是正确的。但有的 操作有一定的先后次序,也就是说它们必须遵循一定的同步规则,只有这样,并发执行的最后 结果才是正确的。我们可以用本章前面介绍的前趋图来描述进程在执行次序上的先后关系。 (4)生产者·消费者问题 生产者-消费者问题是最著名的进程同步问题。它描述了一组生产者向一组消费者提供产 品,它们共享一个有界缓冲区,生产者向其中投放产品,消费者从中取得产品。生产者消费者问 题是许多相互合作进程的一种抽象。例如,在输入时,输入进程是生产者,计算进程是消费者; 在输出时,计算进程是生产者,打印进程是消费者。因此,该问题具有很大实用价值。 我们把一个长度为 n 的有界缓冲区(n〉O)与一群生产者进程 P1、P2、…、Pm 和一群消费 者进程 CI、C2、…、CK 联系起来。假定这些生产者和消费者是互相等效的。只要缓冲区未满, 生产者就可以把产品送入缓冲区,类似地,只要缓冲区未空,消费者便可以从缓冲区中取走物 品并消耗它。生产者和消费者的同步关系将禁止生产者向满的缓冲区输送产品,也禁止消费者 从空的缓冲区中提取物品。 为解决这一类生产者-消费者问题,应该设置两个同步信号量,一个说明空缓冲单元的数 目,用 empty 表示,其初值为有界缓冲区的大小 n,另一个说明满缓冲单元的数目,用 full 表示, 其初值为 0。在本例中有 P1、P2、…、Pm 个生产者和 C1、C2、…、CK 个消费者,它们在执行 生产活动和消费活动中要对有界缓冲区进行操作。由于有界缓冲区是一个临界资源,必须互斥 使用,所以,另外还需设置一个互斥信号量 mutex,其初值为 1。生产者.消费者问题的同步描述 如下: int full=0; /*申满缓冲单元的数目*/ int empty=n; /*空缓冲单元的数目*/
int mutex=l /*对有界缓冲区进行操作的互斥信号量* mal regin ducer i() /*=1,2,…,m:j=1,2,…,k*/ consumer j() producer() /*=1,2 while(生产未完成) 生产一个产品 p(mutex); 送一个产品到有界缓冲区; V(fu11); consumers() /*j=1,2,…,k*/ while(还要继续消费) 从有界缓冲区中取产品 V(mutex 消费一个产品 (5)读者与写者问题 在计算机系统中,有些文件是可共享的,当若干个并发进程都要访问某个共享文件时,应 区分是读还是写(修改)文件。显然可允许多个进程同时读文件但不允许在进程读文件时让另 一进程去修改文件,或者有进程在修改文件时让另一进程去读,否则会造成读出的文件内容不 正确。尤其是绝对不允许多个进程同时修改同一文件。这样一类问题称为"读者一写者"问题 为了实现读者与写者的同步和互斥,我们设置一个信号量S,用于读者与写者之间或写者 与写者之间的互斥,初值为"1"。用一个变量rc表示当前正在读的读者个数,当进程可以去读 或读结束后都要改变re的值,因此rc又成为若干读进程的共享变量,它们必须互斥地修改 rc。故必须定义另一个用于互斥的信号量Sr,初值也是"1"。读者一写者问题可描述如下 var S, Sr: semaphore: =1, 1 rc: Interger rc Parbegin
int mutex=1; /*对有界缓冲区进行操作的互斥信号量*/ main( ) { Parbegin producer i( ); /*i=1,2,…,m:j=1,2,…,k*/ consumer j( ); parend } produceri( ) /*i=1,2,…,m*/ { while (生产未完成) { 生产一个产品; p(empty); p(mutex); 送一个产品到有界缓冲区; V(mutex); V(full); } } consumerj( ) /*j=1,2,…,k*/ { while (还要继续消费) p(full); p(mutex); 从有界缓冲区中取产品; V〈mutex〉; v(empty); 消费一个产品; } } (5)读者与写者问题 在计算机系统中,有些文件是可共享的,当若干个并发进程都要访问某个共享文件时,应 区分是读还是写(修改)文件。显然可允许多个进程同时读文件但不允许在进程读文件时让另 一进程去修改文件,或者有进程在修改文件时让另一进程去读,否则会造成读出的文件内容不 正确。尤其是绝对不允许多个进程同时修改同一文件。这样一类问题称为"读者一写者"问题。 为了实现读者与写者的同步和互斥,我们设置一个信号量 S,用于读者与写者之间或写者 与写者之间的互斥,初值为"1"。用一个变量 rc 表示当前正在读的读者个数,当进程可以去读 或读结束后都要改变 rc 的值,因此 rc 又成为若干读进程的共享变量,它们必须互斥地修改 rc。故必须定义另一个用于互斥的信号量 Sr,初值也是"1"。读者一写者问题可描述如下: var S,Sr:semaphorep:=1,1; rc:interger; rc:=0; Parbegin
rc: -rc+ V(Sr) Read file F. if rc=0 then V(S) V(Sr) end process Writer j(j=1, 2,.., k) V (S) Parend 在这个程序中,当有进程在读而使一个请求写的进程阻塞时,如果仍有进程不断地请求读 则写进程将被长期地推迟运行。但在实际的系统中往往希望让写者优先,即当有进程在读文件 时,如果有进程请求写,那么新的读者被拒绝,待现有读者完成读操作后立即让写者运行,只有 当无写者工作时才让读者工作。下面是写者优先的程序。其中信号量S,初值为1,用于读者与 写者或写者与写者之间的互斥;另一信号量Sn,初值为n,表示系统中最多有n个进程可同时进 行操作 var S, Sn: Semaphore: =l, n: process Reader i(i=1.2,., n) read file F Process Wri P(S) P(Sn) V(S) parend 其中 Process Reader i中的P(S),V(S)保证了当有写者要工作时,不让新的读者去
process Reader i(i=1,2,…,m) begin P(Sr); rc:=rc+1; if rc=1 then P(S); V(Sr); Read file F; P(Sr); rc:=rc-1; if rc=O then V(S); V(Sr); end process Writer j(j=1,2,…,k) begin P(S); Write file F; V(S); end; Parend; 在这个程序中,当有进程在读而使一个请求写的进程阻塞时,如果仍有进程不断地请求读 则写进程将被长期地推迟运行。但在实际的系统中往往希望让写者优先,即当有进程在读文件 时,如果有进程请求写,那么新的读者被拒绝,待现有读者完成读操作后立即让写者运行,只有 当无写者工作时才让读者工作。下面是写者优先的程序。其中信号量 S,初值为 1,用于读者与 写者或写者与写者之间的互斥;另一信号量Sn,初值为n,表示系统中最多有n个进程可同时进 行操作: var S,Sn:Semaphore:=1,n; Parbegin process Reader i(i=1.2,…,n) begin P(S); P(Sn); V(S); read file F; V(Sn); Process Writer j(j=1,2,…,k) begin P(S); For i=1 to n do P(Sn); Write file F; for i:=1 to n do V(Sn); V(S) end parend 其中 Process Reader i 中的 P(S),V(S)保证了当有写者要工作时,不让新的读者去
读。 Process Writer j中的第一循环语句保证让正在工作的读者完成读后再执行写,完成写 操作后由第二个循环语句恢复Sn的初值,最后的V(S)用于唤醒被阻塞的读、写进程 3.1.3管程 使用信号量来处理同步问题时,同步操作P(S)和V(S)分散在各个进程中,并遍布整个程 序。这不仅给系统的管理和程序的维护和修改带来了麻烦,两且还会因同步操作的使用不当造 成死锁。为了解决上述问题,又产生了一种新的进程同步工具一管程 1.管程的定义 管程机制提供了与信号量机制相同的表达能力,但它更容易控制。管程是由一组局部的变 量对局部变量进行操作的一组过程以及对局部变量进行初始化 的语句序列构成的一个软件模块,它可用来实现进程同步。取名为 monitor name的管程,其语 去如下 type momtor name=momtor variable declarations procedue entry P1(…) procedure entry Pn(.) begin…end; initialization code 而且,管程具有以下特点 (1)管程内的局部变量只能被局部于管程内的过程所访问:反之亦然,即局部于管程内的 过程只能访问管程内的变量。 (2)任何进程只能通过调用管程提供的过程入口进入管程 (3)任一时刻,最多只能有一个进程在管程中执行 保证进程互斥地进入管程是由编译器负责的。也就是说,管程是一种编程语言的构件,它 的实现需要得到编译器的支持。 2.条件变量 在任何时刻,最多只有一个进程在管程中执行,因此用管程很容易实现互斥,只要将需要 互斥访问的资源用数据结构来描述,并将该数据结构放入管程中便可。若要用管程来实现同步, 则在相应条件不满足时(如临界资源得不到时)必须能够将在管程内执行的进程阻塞。由于阻 塞的原因不同,为了将它们区分开,引入了局部于管程的条件变量。条件变量的定义格式 为: VarXJ: condition。对条件变量只能执行以下两种操作 (1)wait操作。如.wait用来将执行进程挂到与条件变量x相应的等待队列上 (2) signal操作。如X. signal用来唤醒与ⅹ相应的等待队列上的一个进程。值得注意的 是,若没有等待进程,则X. Signal不起任何作用 3.利用管程解决生产者一消费者问题 利用管程来解决生产者一消费者问题,首先必须为它们建立二个管程: type p c=momtor Var in, out, count: integer; Buffer: array [0, n-1] of iter notfull, notempty: condition
读。Process Writer j 中的第一循环语句保证让正在工作的读者完成读后再执行写,完成写 操作后由第二个循环语句恢复 Sn 的初值,最后的 V(S)用于唤醒被阻塞的读、写进程。 3.1.3 管程 使用信号量来处理同步问题时,同步操作 P(S)和 V(S)分散在各个进程中,并遍布整个程 序。这不仅给系统的管理和程序的维护和修改带来了麻烦,两且还会因同步操作的使用不当造 成死锁。为了解决上述问题,又产生了一种新的进程同步工具一管程。 1.管程的定义 管程机制提供了与信号量机制相同的表达能力,但它更容易控制。管程是由一组局部的变 量对局部变量进行操作的一组过程以及对局部变量进行初始化 的语句序列构成的一个软件模块,它可用来实现进程同步。取名为 monitor_name 的管程,其语 法如下: type momtor_name=momtor variable declarations; procedue entry P1(…); begin …end; ┆ procedure entry Pn(…); begin …end; begin initialization code; end 而且,管程具有以下特点: (1)管程内的局部变量只能被局部于管程内的过程所访问:反之亦然,即局部于管程内的 过程只能访问管程内的变量。 (2)任何进程只能通过调用管程提供的过程入口进入管程。 (3)任一时刻,最多只能有一个进程在管程中执行。 保证进程互斥地进入管程是由编译器负责的。也就是说,管程是一种编程语言的构件,它 的实现需要得到编译器的支持。 2.条件变量 在任何时刻,最多只有一个进程在管程中执行,因此用管程很容易实现互斥,只要将需要 互斥访问的资源用数据结构来描述,并将该数据结构放入管程中便可。若要用管程来实现同步, 则在相应条件不满足时(如临界资源得不到时)必须能够将在管程内执行的进程阻塞。由于阻 塞的原因不同,为了将它们区分开,引入了局部于管程的条件变量。条件变量的定义格式 为:VarXJ:condition。对条件变量只能执行以下两种操作: (1)wait 操作。如 X.Wait 用来将执行进程挂到与条件变量 x 相应的等待队列上。 (2)signal 操作。如 X.signal 用来唤醒与 x 相应的等待队列上的一个进程。值得注意的 是,若没有等待进程,则 X.Signal 不起任何作用。 3.利用管程解决生产者一消费者问题 利用管程来解决生产者一消费者问题,首先必须为它们建立二个管程: type p_c=momtor Var in,out,count:integer; Buffer:array[0,…,n-1] of item; notfull,notempty:condition;
procedure entry put(var product: item) if count≥ n then notfull.wait;/*等待缓冲池不全满条件成立*/ buffer[in]: =product n:=(in+1)mod count: =count+1 notempty. signal;/*缓冲池不全空条件成立*/ procedure entry get(Var product: item) begin f count≤ Othen notempty.wait;/*等待缓冲池不全空条件成立*/ product: =buffer [out] out: =(out+1)mod n count: =count-1 notfull signal;/*缓冲池不全满条件成立*/ begil count: =0 上述管程Pc中包括两个局部过程:过程put负责将产品投放到缓冲池中;过程get负责 从缓冲池中取出产品。另外,整型变量 count表示缓冲池中己存放的产品数目,条件变量 notfull、 notempty分别对应于缓冲池不全满、缓冲池不全空两个条件 而相应的生产者和消费者可描述为: producer: begin produce an item in nextp P c put (nextp) until false end consumer: begin repeat P c get(nextc) consume the item in next until false 3.1.4进程通信 进程间的信息交换称为进程通信。进程之间的互斥与同步就是一种进程间的通信方式 由于进程互斥与同步交换的信息量较少且效率较低,因此称这两种通信方式为低级通信方式, 相应地也可将P、V操作称为两条低级通信原语。所谓高级通信方式是指进程之间以较高的效 率传送大量数据的通信方式。 1.进程通信的类型 高级通信方式可分为三大类:共享存储器系统、消息传递系统以及管道通信系统
procedure entry put(Var product:item) begin if count≥n then notfull.wait; /*等待缓冲池不全满条件成立*/ buffer[in]:=product; in:=(in+1)mod n; count:=count+1; notempty.signal; /*缓冲池不全空条件成立*/ end procedure entry get(Var product:item) begin if count≤Othen notempty.wait; /*等待缓冲池不全空条件成立*/ product:=buffer[out]; out:=(out+1)mod n; count:=count-1; notfull.signal; /*缓冲池不全满条件成立*/ end begin in:=out:=0; count:=0; end 上述管程 P_c 中包括两个局部过程:过程 put 负责将产品投放到缓冲池中;过程 get 负责 从缓冲池中取出产品。另外,整型变量 count 表示缓冲池中己存放的产品数目,条件变量 notfull、notempty 分别对应于缓冲池不全满、缓冲池不全空两个条件。 而相应的生产者和消费者可描述为: producer:begin repeat produce an item in nextp; P_c.put(nextp); until false end consumer:begin repeat P_c.get(nextc); consume the item in nextc; until false end 3.1.4 进程通信 进程间的信息交换称为进程通信。进程之间的互斥与同步就是一种进程间的通信方式。 由于进程互斥与同步交换的信息量较少且效率较低,因此称这两种通信方式为低级通信方式, 相应地也可将 P、V 操作称为两条低级通信原语。所谓高级通信方式是指进程之间以较高的效 率传送大量数据的通信方式。 1.进程通信的类型 高级通信方式可分为三大类:共享存储器系统、消息传递系统以及管道通信系统
(1)共享存储器系统。高级通信中的共享存储器系统是指进程之间通过对共享存储区的读 写来交换数据。共享存储器系统的另一种方式是利用共享的数据结构来进行进程通信,但这种 方式对共享数据结构的设置及对进程间的同步都必须由程序员来处理,且只能进行少量的数 据交换,因此属于低级通信方式 (2)消息传递系统。消息传递系统中,进程间的数据交换以格式化的消息(网络中称作报 文)为单位。根据实现方式,它又可分为直接通信和间接通信两类。在直接通信方式中,源进程 可直接将消息发送给目标进程,此类操作系统通常提供send( recelver, message)和 receive( sender, message)两条通信命令(原语)供用户使用。在间接通信方式中,进程间需要 通过某种中间实体(即信箱)来进行通信,发送进程将消息投入信箱,而接收进程则从信箱中疆 取得消息,因此,它不仅能实现实时通信,还能实现非实时通信。此时,操作系统应提供若干条 原语分别用于信箱的创建、撤消和消息的发送、接收等。 (3)管道通信。所谓″管道"是指连接i两个进程的一个打开的共享文件,发送进程以字符 流的形式将大量的信息写入管道,接收进程则在需要时从管道中读出数据。为了协调双方的通 信,管道通信机制必须对发送进程和接收进程在利用管道进行通信时实施同步和互斥,并只有 在确定了对方存在时方能进行通信 3.1.5线程 1.线程的基本概念 引入线程的目的是为了减少程序在并发执行时所付出的时空开销,从而使0S具有更好的 并发性。在多线程os中,将拥有资源的基本单位与调度和分派的基本单位分开处理。此时 个进程中含有一个或多个相对独立的线程,进程只是拥有资源的基本单位,每个线程都是一 个可执行的实体,即CPU调度和分派的基本单位是线程。 线程可以利用线程标识符和一组状态参数来描述,并具有下述属性 (1)轻型实体。线程除了在运行中必不可少的资源(如线程控制块、程序计数器、一组寄存 器值和堆栈)外,线程基本上不拥有系统的资源。 (2)独立调度和分派的基本单位。线程是能独立运行的基本单位,因而也是独立调度和分派 的基本单位,为此,线程中必须包含调度所必需的信息 (3)可并发执行。同一个进程中的多个线程,以及不同进程中的多个线程均可以并发地执 (4)共享进程资源。同一个进程中的各线程可以共享该进程所拥有的全部资源,如进程的地 址空间、己打开的文件、定时器和信号量机构等 由于线程基本不拥有资源,创建线程时不需另行分配资源,终止时也不需要进行资源的回 收,而切换时也大大减少了需保存和恢复的现场信息,因此,线程的创建、终止和切换都要比进 程迅速且开销小。另外,同一进程中的各线程可以共享该进程所占用的内存空间和已打开文件, 因此,线程间通信也非常简便和迅速 2.线程的控制 在多线程0S环境下,应用程序在启动时,0S将为它创建一个进程,同时为该进程创建第 个线程。以后在线程的运行过程中,它可根据需要利用线程创建函数(或系统调用)再去创建若 个线程。所以线程是由线程创建的,但线程间并不提供父子关系的支持 每个线程被创建后,便可与其他线程一起并发地运行。如同传统的进程一样,并发运行的 线程之间也存在着共享资源和相互合作的制约关系,致使线程在运行时也具有间断性。相应地, 线程在运行时,也具有执行、就绪、阻塞三种基本状态,并随着自身的运行和外界环境的变换 而不断地在三种状态之间转换 当线程完成了自己的工作后,它便可正常终止。线程的终止也可能是因为运行中出现错误
(1)共享存储器系统。高级通信中的共享存储器系统是指进程之间通过对共享存储区的读 写来交换数据。共享存储器系统的另一种方式是利用共享的数据结构来进行进程通信,但这种 方式对共享数据结构的设置及对进程间的同步都必须由程序员来处理,且只能进行少量的数 据交换,因此属于低级通信方式。 (2)消息传递系统。消息传递系统中,进程间的数据交换以格式化的消息(网络中称作报 文)为单位。根据实现方式,它又可分为直接通信和间接通信两类。在直接通信方式中,源进程 可直接将消息 发送给目 标进程, 此类操作 系统通常 提供 send(receiver,message)和 receive(sender,message)两条通信命令(原语)供用户使用。在间接通信方式中,进程间需要 通过某种中间实体(即信箱)来进行通信,发送进程将消息投入信箱,而接收进程则从信箱中疆 取得消息,因此,它不仅能实现实时通信,还能实现非实时通信。此时,操作系统应提供若干条 原语分别用于信箱的创建、撤消和消息的发送、接收等。 (3)管道通信。所谓"管道"是指连接 i 两个进程的一个打开的共享文件,发送进程以字符 流的形式将大量的信息写入管道,接收进程则在需要时从管道中读出数据。为了协调双方的通 信,管道通信机制必须对发送进程和接收进程在利用管道进行通信时实施同步和互斥,并只有 在确定了对方存在时方能进行通信。 3.1.5 线程 1.线程的基本概念 引入线程的目的是为了减少程序在并发执行时所付出的时空开销,从而使 OS 具有更好的 并发性。在多线程 os 中,将拥有资源的基本单位与调度和分派的基本单位分开处理。此时, 一个进程中含有一个或多个相对独立的线程,进程只是拥有资源的基本单位,每个线程都是一 个可执行的实体,即 CPU 调度和分派的基本单位是线程。 线程可以利用线程标识符和一组状态参数来描述,并具有下述属性: (1)轻型实体。线程除了在运行中必不可少的资源(如线程控制块、程序计数器、一组寄存 器值和堆栈)外,线程基本上不拥有系统的资源。 (2)独立调度和分派的基本单位。线程是能独立运行的基本单位,因而也是独立调度和分派 的基本单位,为此,线程中必须包含调度所必需的信息。 (3)可并发执行。同一个进程中的多个线程,以及不同进程中的多个线程均可以并发地执 行。 (4)共享进程资源。同一个进程中的各线程可以共享该进程所拥有的全部资源,如进程的地 址空间、己打开的文件、定时器和信号量机构等。 由于线程基本不拥有资源,创建线程时不需另行分配资源,终止时也不需要进行资源的回 收,而切换时也大大减少了需保存和恢复的现场信息,因此,线程的创建、终止和切换都要比进 程迅速且开销小。另外,同一进程中的各线程可以共享该进程所占用的内存空间和已打开文件, 因此,线程间通信也非常简便和迅速。 2.线程的控制 在多线程 OS 环境下,应用程序在启动时,OS 将为它创建一个进程,同时为该进程创建第一 个线程。以后在线程的运行过程中,它可根据需要利用线程创建函数(或系统调用)再去创建若 干个线程。所以线程是由线程创建的,但线程间并不提供父子关系的支持。 每个线程被创建后,便可与其他线程一起并发地运行。如同传统的进程一样,并发运行的 线程之间也存在着共享资源和相互合作的制约关系,致使线程在运行时也具有间断性。相应地, 线程在运行时,也具有执行、就绪、阻塞三种基本状态,并随着自身的运行和外界环境的变换 而不断地在三种状态之间转换。 当线程完成了自己的工作后,它便可正常终止。线程的终止也可能是因为运行中出现错误
或某种其他原因而引起的,此时它是被强行终止的。可见,线程如同进程一样,具有一定的生命 周期。 3.线程的同步 在多线程os中通常提供多种同步机制,如互斥锁、条件变量、信号量机制以及多读、单 写锁等,它们可支持不同频率的交互操作和不同程度的并行性。 (1)互斥锁 互斥锁有开锁和关锁两种状态,并能进行关锁和开锁两种操作。当一个线程需要访问某个 临界资源时,线程首先应对为该资源所设置的互斥锁 mutex进行关锁操作 mutex enter:判别 mutex的状态,如果它已处于关锁状态,则试图访问该资源的线程将被阻塞;而如果mtex处于 开锁状态,则将mtex关上后便可访问该资源。在线程完成对共享资源的访问后,必须执行开 锁操作 mutex-exit:如果有线程阻塞在该互斥锁上,则唤醒其中的一个线程;而如果没有阻塞 的线程,则将互斥锁的状态置成开锁状态。为了降低线程被阻塞的频率,在有的系统中还提供 了一种不阻塞的关锁操作 mutex tryenter,当 mutex处于关锁状态时, mutex tryenter并不阻 塞线程,而只是返回一个指示操作失败的状态码。 互斥锁是一种比较简单的同步机制,而且是严格括入的( bracketing),一个线程去打开被 另一线程关闭的互斥锁将是错误的,因此它只适用于实现线程对资源的互斥访问。由于操作互 斥锁的时间和空间开销都较低,因而它较适合于高频度使用的关键共享数据和程序段。 (2)条件变量 条件变量必须和互斥锁配合起来使用,它用于等待,直到某一特定条件为真。对条件变量 的 cv walt操作将使线程阻塞,直到所等的条件信号成立后,才能由 cv signal操作将其中的 个阻塞线程唤醒。 cv wait操作在阻塞线程前将对相应的互斥锁执行开锁操作,并在返回前 重新对互斥锁进行关锁操作。条件变量可用来实现互斥或同步,它的典型使用方式为 mutex enter(&mutex) hile(some condition)( cv wait(&cv, &mutex) mutex exit(&mutex) 这里允许条件是一个复杂的表达式,因为它受互斥锁的保护。 (3)信号量机制 信号量机制也可用于多线程os中,实现诸线程或进程之间的同步。为了提高效率,可为线程和 进程分别设置相应的信号量。 当某线程利用信号量来实现同一进程中各线程之间的同步时,可调用创建信号量命令来创 建一私用信号量,其数据结构被存放在应用程序的地址空间中。私用信号量属于特定的进程所 有,0S并不知道私用信号量的存在,因此,一旦发生私用信号量的占用者异常结束或正常结束, 但并未释放该信号量所占用的空间时,系统无法使它恢复为0(空),也不能将它传送给下一个 请求它的线程 当要实现不同进程间或不同进程中各线程之间的同步时,则可由系统为它们创建一个公用 信号量,其数据结构存放在受保护的系统存储区中,并由os为它分配空间并进行管理,故也称 其为系统信号量。如果信号量的占有者在结束时未释放该公用信号量,则0S会自动将该信号 量空间回收,并通知下一个进程。可见,公用信号量是一种比较安全的同步机制 4.内核支持线程和用户级线程 线程己在许多系统中实现,但实现的方式并不完全相同。有些系统中,特别是一些数据库
或某种其他原因而引起的,此时它是被强行终止的。可见,线程如同进程一样,具有一定的生命 周期。 3.线程的同步 在多线程 os 中通常提供多种同步机制,如互斥锁、条件变量、信号量机制以及多读、单 写锁等,它们可支持不同频率的交互操作和不同程度的并行性。 (1)互斥锁 互斥锁有开锁和关锁两种状态,并能进行关锁和开锁两种操作。当一个线程需要访问某个 临界资源时,线程首先应对为该资源所设置的互斥锁 mutex 进行关锁操作 mutex_enter:判别 mutex的状态,如果它已处于关锁状态,则试图访问该资源的线程将被阻塞;而如果mutex处于 开锁状态,则将 mutex 关上后便可访问该资源。在线程完成对共享资源的访问后,必须执行开 锁操作 mutex-exit:如果有线程阻塞在该互斥锁上,则唤醒其中的一个线程;而如果没有阻塞 的线程,则将互斥锁的状态置成开锁状态。为了降低线程被阻塞的频率,在有的系统中还提供 了一种不阻塞的关锁操作mutex_tryenter,当mutex处于关锁状态时,mutex_tryenter并不阻 塞线程,而只是返回一个指示操作失败的状态码。 互斥锁是一种比较简单的同步机制,而且是严格括入的(bracketing),一个线程去打开被 另一线程关闭的互斥锁将是错误的,因此它只适用于实现线程对资源的互斥访问。由于操作互 斥锁的时间和空间开销都较低,因而它较适合于高频度使用的关键共享数据和程序段。 (2)条件变量 条件变量必须和互斥锁配合起来使用,它用于等待,直到某一特定条件为真。对条件变量 的 cv_wait 操作将使线程阻塞,直到所等的条件信号成立后,才能由 cv_signal 操作将其中的 一个阻塞线程唤醒。cv_wait 操作在阻塞线程前将对相应的互斥锁执行开锁操作,并在返回前 重新对互斥锁进行关锁操作。条件变量可用来实现互斥或同步,它的典型使用方式为: mutex_enter(&mutex); ┇ while(some_condition){ cv_wait(&cv,&mutex); } ┇ mutex_exit(&mutex); 这里允许条件是一个复杂的表达式,因为它受互斥锁的保护。 (3)信号量机制 信号量机制也可用于多线程 os 中,实现诸线程或进程之间的同步。为了提高效率,可为线程和 进程分别设置相应的信号量。 当某线程利用信号量来实现同一进程中各线程之间的同步时,可调用创建信号量命令来创 建一私用信号量,其数据结构被存放在应用程序的地址空间中。私用信号量属于特定的进程所 有,OS 并不知道私用信号量的存在,因此,一旦发生私用信号量的占用者异常结束或正常结束, 但并未释放该信号量所占用的空间时,系统无法使它恢复为 0(空),也不能将它传送给下一个 请求它的线程。 当要实现不同进程间或不同进程中各线程之间的同步时,则可由系统为它们创建-个公用 信号量,其数据结构存放在受保护的系统存储区中,并由 os 为它分配空间并进行管理,故也称 其为系统信号量。如果信号量的占有者在结束时未释放该公用信号量,则 OS 会自动将该信号 量空间回收,并通知下一个进程。可见,公用信号量是一种比较安全的同步机制。 4.内核支持线程和用户级线程 线程己在许多系统中实现,但实现的方式并不完全相同。有些系统中,特别是一些数据库