首页 操作系统概念第四章 进程

操作系统概念第四章 进程

举报
开通vip

操作系统概念第四章 进程 http://www.tulipsys.com 操作系统概念(第六版) 第四章 进程 更新日期:2004-8-12 0:37 早期的计算机只允许同时运行一个程序。这个程序完全控制计算机并能够访问所有的系统资源。当今 的计算机系统允许同时将多个程序载入内存并行执行。这种发展需要更稳固的控制和对各种程序更合理的 分类。这些需要造就了进程的概念,进程是执行中的程序(The process is a program in execution.)。在现代 分时系统中,一个进程是一个工作单元。 操作系统越复杂...

操作系统概念第四章 进程
http://www.tulipsys.com 操作系统概念(第六版) 第四章 进程 更新日期:2004-8-12 0:37 早期的计算机只允许同时运行一个程序。这个程序完全控制计算机并能够访问所有的系统资源。当今 的计算机系统允许同时将多个程序载入内存并行执行。这种发展需要更稳固的控制和对各种程序更合理的 分类。这些需要造就了进程的概念,进程是执行中的程序(The process is a program in execution.)。在现代 分时系统中,一个进程是一个工作单元。 操作系统越复杂,期望它能够为用户做的事情越多。虽然它主要关注用户程序的执行,但是也需要处 理内核自身之外的各种系统任务。所以系统由进程集合组成:操作系统进程执行系统代码,用户进程执行 用户代码。通过 CPU在进程间多路复用,所有这些进程潜在的能够并行执行。通过在进程间转换 CPU, 操作系统可以使计算机获得更好的性能。 4.1 进程概念 在讨论操作系统时所遇到的一个问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 是怎样定义 CPU 活动。(One impediment to our discussion of operating systems is the question of what to call all the CPU activities.)批处理系统执行作业,而分时系统拥有 用户程序或任务。甚至在单用户系统(如 Microsoft Windows和 Macintosh OS)中,一个用户也可以同时 运行多个程序:一个字处理软件、网页浏览器和电子邮件包。即使用户同时只能够执行一个程序,操作系 统可能需要支持其内部程序化的活动(如存储器管理)。在许多方面,这些活动是相似的,因此我们称之 为进程。 在本书中,术语“作业”和“进程”几乎是可以交换使用的。虽然我(们)个人更倾向于术语“进程”, 但是在操作系统的主要活动被作为作业处理的一段时期内许多的操作系统理论和术语不断发展。使用公认 的术语可以避免很多误解,这包括了单词 job(如 job scheduling),仅仅是因为“进程”已经取代了“作业”。 4.1.1 进程 非正式的,进程是运行中的程序。进程不仅仅是程序代码,有时也称之为代码段(text section)。它也 包含了当前的状态,这由程序计数器和处理器中的寄存器表示。另外,进程通常包含了进程栈(process stack) (如 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 参数(method parameters)、返回地址和本地变量)和一个数据段(存储全局变量)。 我们强调程序本身不是进程;程序是静态实体(就像是存储在磁盘上的文件),进程是动态实体,它 有一个程序计数器指明下一条要执行的指令,并且拥有一组相关的资源。 虽然两个进程可能会关联到同样的程序,但仍被视为两个独立的执行序列。例如,几个用户可能会同 时运行主程序的不同拷贝,用户也可能会执行多个编辑程序拷贝。那么其中的每一个都是一个独立的进程, 而且虽然其文本段是相同的,但是数据段不同。一个进程运行时产生多个进程也是很普遍的。我们将在 4.4 节讨论这些。 4.1.2 进程状态 在进程运行时,它会改变自身状态。进程的状态部分由该进程的当前活动定义。每个进程可能会处于 下列几种状态之一: l 新:进程正被创建。 l 运行:(进程的)指令正被执行。 l 等待:进程正在等待发生一些事件(如 I/O完成或接收一个信号)。 l 就绪:进程正等待分配处理器。 l 终止:进程结束运行。 这些状态名称是任意的,各个操作系统有着不尽相同的定义。然而可以在所有的系统中找到对状态的 表示。某些操作系统更好的描述了进程状态。虽然可能有多个进程处于就绪和等待状态,但是处理器(不 管是什么样的处理器)任意时刻只能执行一个进程。图 4.1表示了相应的状态图。 http://www.tulipsys.com Figure 4.1 Diagram of process state 4.1.3 进程控制块 操作系统通过进程控制块(PCB)表示进程,进程控制块也被称为任务控制块。图 4.2 描述了一个进 程控制块。它存储了某一具体进程的信息,这包括: Figure 4.2 Process control block (PCB). l 进程状态:该状态可能是新、就绪、运行、等待、停止等等。 l 程序计数器:该计数器指明了该进程要执行的下一条指令的地址。 l CPU寄存器:基于计算机体系结构,这些寄存器的数量和类型很不相同。这包括了累加器、 变址寄存器、栈指针、通用寄存器,以及条件信息(condition-code information)。连同程序 计数器,在中断发生时必须要保存这些状态信息,这样便于后来进程继续正确执行(图 4.3)。 http://www.tulipsys.com l CPU调度信息:包括进程优先权、指向调度队列的指针和其它的调度参数。(第六章描述进 程调度。) l 存储器管理信息:可能包括诸如基址寄存器和界限寄存器值、页表或段表,这取决于操作系 统所选用的存储系统(第九章)。 l 记账信息(accounting information):包括 CPU数量和实时使用量、时间限制、账户数目、 作业或进程数目等等。 l I/O状态信息:包括分配给该进程的 I/O设备的列表、打开的文件的列表等等。 Figure 4.3 Diagram showing CPU switch from process to process. PCB只是存储信息,而进程间的这些信息是不同的。 4.1.4 线程 目前为止,进程意味着是执行单个线程的程序。例如,如果一个进程正在运行一个字处理程序,那么 就会执行一个单指令线程。这个单独的控制执行序列允许进程只执行一个任务。(This single thread of control allows the process to perform only one task at one time.)例如,用户不能够在同一个进程中同时键入字符和运 行拼写检查程序。许多现代操作系统扩展了进程概念,允许一个进程有多个线程。从而允许进程一次执行 多个任务。第五章探讨了多线程进程(multithreaded process)。 4.2 进程调度 多道程序设计的目标是为了保持总是有多个进程运行,以最大化 CPU 利用率。分时系统的目标是为 了在进程之间频繁转换 CPU 以便于用户与运行的程序交互。一个单处理机系统只能够执行一个进程。如 果存在更多的进程,那么其他的进程必须要等待 CPU空闲下来才能够被调度。 4.2.1 调度队列 http://www.tulipsys.com 进程进入系统之后,它们被放到作业队列里。这个队列由系统中的所有进程组成。驻留在主存储器中 处与就绪状态等待执行的进程被保留在一个列表中,这个列表被称为就绪队列。这个队列通常存储为链表。 就绪队列的头部保存了指向列表中首个和最后一个 PCB的指针。我们扩展了每个 PCB,使他们包含一个 指针字段来指向就绪队列中的下一个 PCB。 操作系统也有其它的队列。当一个进程分配到 CPU 时,它执行一段时间并最终退出、被中断或等待 特定事件的发生(如一个 I/O请求的完成)。在等待 I/O请求的情况下,这样的一个请求可能会针对一个磁 带驱动器或一个共享设备(如磁盘)。因为系统中有多个进程,所以磁盘可能会忙于应付其它进程的 I/O请 求。因此这个进程必须要等到磁盘空闲下来。等待某一特定 I/O设备的进程列表被称为设备队列。每个设 备都有自己的设备队列(图 4.4)。 Figure 4.4 The ready queue and various I/O device queues. 一个通用的进程调度的表示法是队列状态图(queueing diagram),如图 4.5。每个矩形框表示一个队 列。有两种类型的队列:就绪队列和设备队列。圆圈表示服务于队列的资源,箭头指示系统中的进程流。 新进程最初被放在就绪队列中。它在就绪队列中等待,直到被选中执行(或调度)。一旦进程获得了 CPU并执行,可能会发生下面的某个事件: l 进程可能发出一个 I/O请求,然后被放置在 I/O 队列中。 l 进程可以创建新的子进程并等待它终止。 l 发生一个中断,导致进程被强行从 CPU中移出并返回就绪队列。 http://www.tulipsys.com Figure 4.5 Queueing-diagram representation of process scheduling. 在前两种情况下,进程最终会从等待状态转换为就绪状态,并返回就绪队列中。一个进程会持续这个 循环直到终止执行,此时退出所有对列并释放自己的 PCB和资源。 4.2.2 调度程序 进程在其生命周期中于各种调度队列之间转移。为了进行调度,操作系统必须要以某种方式从这些队 列里选择进程。而调度程序负责选择进程。 在批处理系统中,提交的进程数量常常要多于能够立即执行的进程数量。这些进程存储在大容量存储 器(典型的是磁盘)中以备稍后执行。长程调度程序(或作业调度程序)从这个池中选择进程并将其载入 内存。近程调度程序(或 CPU调度程序)从这些进程中选择就绪进程并为其中某个分配 CPU。 这两种调度程序的主要区别在于他们的运行频率。短程调度程序必须要频繁的为 CPU 选择一个新进 程。一个进程可能在等待一个 I/O请求之前仅仅执行数毫秒。通常短程调度程序至少每隔 100毫秒执行一 次。因为两次执行的间隔时间很短,所以短程调度程序必须要快速。如果它需要 10毫秒来决定一个进程, 而进程运行 100毫秒,那么 10/(100 + 10) = 9%的 CPU仅仅被用于调度工作(或者说是浪费在调度工作上)。 另一方面,长程调度程序就不那么频繁执行了。在系统中,可能数分钟才会创建一个新进程。长程调 度程序控制着多道程序度——内存中(同时存在)的进程数量。如果多道程序度是固定的,那么进程创建 的平均频率要与进程(终止)离开系统的平均频率相同。如此,长程调度程序可能仅仅在进程离开系统的 时候被调用。因为两次执行的间隔时间较长,所以长程调度程序能够提供更多的时间来选择一个进程。 长程调度程序必须要小心选择。通常,大多数的进程是 I/O繁忙型(I/O bound)或 CPU繁忙型(CPU bound)。I/O繁忙型进程在 I/O上耗费的时间要多于在计算上耗费的。另一方面,CPU繁忙型进程很少产 生 I/O请求,与 I/O繁忙型进程相比更多的时间消耗在计算上。长程调度程序应该选择一个由 I/O繁忙型 和 CPU繁忙型进程组成的进程混合集(process mix)。如果所有的进程都是 I/O繁忙型的,那么就绪队列 几乎总是空的,而且短程调度程序几乎无事可做。如果所有的进程都是 CPU繁忙型的,那么 I/O等待队列 几乎总是空的,设备将处于空闲状态,系统将失去平衡。性能最好的系统要有一个 CPU繁忙型和 I/O繁忙 型进程的组合。 有些系统中的长程调度程序可能没有或很小。例如,分时系统(如 UNIX)常常没有长程调度程序, 只是简单的为短程调度程序把新进程放置到内存中。这些系统的稳定性取决于实际的条件限制(如可用的 终端的数量)或用户的自我调节。如果性能下降到不可接受的地步,只是简单的使部分用户退出。 有些操作系统(如分时系统)可能会引入另外一种中间级的调度。图 4.6描述了这种中程调度程序, http://www.tulipsys.com 将进程从内存中移除(不再占用 CPU)并降低了多道程序度。稍后再把进程重新载入内存并从停止的地方 继续运行。这种机制被称为交换。通过中程调度程序,进程被换出,然后被换入。为了改善进程混合集, 或者内存需求过多或者太多空闲了,就有必要进行交换。第九章讨论交换技术。 Figure 4.6 Addition of medium-term scheduling to the queueing diagram. 4.2.3 上下文转换 要将 CPU 转向另一个进程需要保存当前进程的状态并载入为新进程存储的状态。这个工作被称为上 下文转换。一个进程的上下文表示在进程的 PCB中;它包括了 CPU寄存器值、进程状态(图 4.1)和内存 管理信息。当上下文转换发生时,内核存储当前进程 PCB中的上下文信息并载入被调度运行的新进程存储 的上下文信息。上下文转换时间是纯粹的开销,因为在转换进行时系统不能做任何有用的工作。根据内存 速度、必须要拷贝的寄存器数量和是否存在用于上下文转换的专门指令(例如有独立的指令来载入或存储 所有的寄存器),转换速度与具体的机器有关。典型的速度范围在 1到 1000 毫秒之间。 上下文转换时间在很大程度上取决于硬件的支持。例如,有些处理器(如 Sun UltraSPARC)提供了多 个寄存器组。上下文转换只是将指针指向当前寄存器组。当然,如果活动的进程太多,超过了寄存器组的 数目,那么就需要像以前那样将寄存器里面的数据转移到内存中了。(Of course, if active processes exceed register sets, the system resorts to copying register data to and from memory, as before.)而且,操作系统越复杂, 上下文转换中的工作就越多。就像我们将在第九章中看到的那样,高级内存管理在上下文转换中需要处理 额外的数据。例如,必须要保存当前进程的地址空间,因为这个地址空间将作为下一个任务的地址空间准 备使用。怎样保存地址空间和保存它需要作什么工作基于操作系统的存储器管理策略。就像我们将在第五 章中看到的那样,上下文转换成了一个性能瓶颈,只要有可能,程序就会使用新的结构(线程)来避免。 4.3 进程上的操作 进程在系统中能够并行执行,并且它们必须要动态的创建和删除。因此,操作系统必须要提供进程创 建和终止的机制(或方法)。 4.3.1进程的创建 进程在运行期间通过创建进程系统调用可以创建多个新进程。创建进程的进程(the creating process) 被称为父进程(parent),而新进程被称为子进程(children)。每个新进程都可以创建另外的进程,从而形 成一个进程树(图 4.7)。 通常一个进程需要特定的资源(如 CPU时间、内存、文件、I/O 设备)。当一个进程创建了一个子进 程时,这个子进程可能直接从操作系统获取它所需的资源或者获取父进程资源的一部分。父进程可能必须 要把自己的资源分配给它的子进程,也可能在它的若干个子进程之间共享某些资源(如内存或文件)。通 过限制子进程只能够获取父进程的部分资源可以阻止进程通过创建过多的子进程而导致系统过载。 当一个进程被创建时,除了获取各种物理和逻辑资源外,初始化数据(或输入)可能也要从父进程传 http://www.tulipsys.com 送给子进程。例如,考虑一个进程,它的功能是在终端屏幕上显示一个文件(Fl)的状态信息。当它被创 建时,它将获得文件 Fl的名称(作为来自其父进程的一个输入)并且将利用这个数据来获取所需的信息。 它可能也会获取输出设备的名称。有些操作系统将资源传递给子进程。在这样的系统中,新进程可能会获 取两个打开文件,Fl和终端设备,并且可能只需在二者之间传输数据。 Figure 4.7 A tree of processes on a typical UNIX system. 当一个进程创建了一个新进程时,会以两种可能的方式执行: 1. 父进程(继续执行)与子进程并行执行。 2. 父进程等待部分或全部子进程终止执行。 新进程的地址空间也有两种可能: 1. 子进程是父进程的一个拷贝。(The child process is a duplicate of the parent process. ) 2. 载入一个程序运行。(The child process has a program loaded into it. ) 为了阐明这两种不同的实现,让我们参考 UNIX操作系统。在 UNIX中,进程通过进程标识符来识别,进 程标识符是一个唯一的整数。通过 fork系统调用创建一个新进程。新进程由原始进程的地址空间的一个拷 贝构成。(The new process consists of a copy of the address space of the original process.)这种机制允许父进程 简易的与子进程通信。两个进程(父进程和子进程)在 fork系统调用之后继续执行,但是有一点不同:在 新(子)进程中 fork 的返回码是零,而父进程中 fork的返回码是子进程的进程号(非零)。 一般父进程或子进程(为了开始一个新程序)在 fork系统调用之后调用 execlp 系统调用来载入一个新 程序到自己的地址空间中。execlp 系统调用将一个二进制文件载入内存(销毁包含着 execlp 系统调用的程 序的内存映象)并开始运行它。以这种方式,两个进程可以通信,然后各自为政。于是父进程可以创建更 多的子进程,或者,如果父进程在子进程运行期间无事可做,他就执行一个 wait 系统调用把自己移出等待 队列直到子进程终止。图 4.8中的 C程序演示了先前描述的 UNIX系统调用。父进程利用 fork系统调用创 建一个子进程。现在就有了两个不同的进程来运行同一个程序的拷贝。子进程的 pid 值为 0;父进程的是 一个大于 0的整型数。子进程利用 execlp 系统调用把 UNIX command/bin/Is (用于获取一个目录列表)覆 盖到自己的地址空间。父进程通过 wait 系统调用等待子进程完成。当子进程完成时,父进程从调用 wait http://www.tulipsys.com 的地方重新开始,运行完成后调用 exit 系统调用(退出)。(原文:When the child process completes, the parent process resumes from the call to wait where it completes using the exit system call. 怀疑作者有误,应为:When the child process completes, the parent process resumes from the call to wait, when it completes using the exit system call.) DEC VMS 操作系统则正相反,它创建一个新进程,载入一个指定的程序,然后开始运行。Microsoft Windows NT 操作系统支持这两种模型:拷贝父进程的地址空间,或者是父进程指定一个程序并由操作系 统将其载入到新进程的地址空间中。(The Microsoft Windows NT operating system supports both models: The parent's address space may be duplicated, or the parent may specify the name of a program for the operating system to load into the address space of the new process.) Figure 4.8 C program forking a separate process. 4.3.2 进程的终止 进程执行完最后一条语句后就终止执行,并调用 exit 系统调用来使操作系统删除它。在此,该进程可 能要把数据(输出)返回给它的父进程(通过 wait 系统调用)。操作系统回收该进程的所有资源——包括 物理和虚拟内存、打开文件和 I/O缓冲器。 http://www.tulipsys.com 进程也可能在其它的情况下终止运行。一个进程可以利用系统调用(例如:abort)终止其它的进程。 通常,只有进程的父进程可以调用这样的系统调用来终止它。否则,用户可以任意的取消其它用户的作业。 所以父进程需要知道其子进程的标识符。如此,当一个进程创建一个新进程时,新创建的进程的标识符要 传给其父进程。 父进程可能会出于某个原因而结束它的一个子进程,例如: l 子进程需要更多的资源。(The child has exceeded its usage of some of the resources that it has been allocated.)这需要父进程能够检查其子进程的状态。 l 分配给子进程的任务已经不再需要。 l 父进程退出,而且操作系统禁止子进程在父进程终止后继续执行。在这样的系统中,如果一个进程 (正常或非正常)终止,那么它的所有子进程也必须要终止。这种级联式的进程终止通常是操作系 统发起的。(This phenomenon, referred to as cascading termination, is normally initiated by the operating system.) 为了举例进程的执行和终止,在 UNIX系统中我们能够通过调用 exit 系统调用终止一个进程;它的父进程 可能通过 wait 系统调用等待一个子进程的终止。wait 系统调用返回终止的子进程的标识符,所以父进程可 以知道它的哪个子进程终止了。如果父进程终止,它所有的子进程都将 init 进程设为自己的父进程。(If the parent terminates, however, all its children have assigned as their new parent the init process.)从而子进程仍旧有 一个父进程来维护它们的状态和运行统计数据(execution statistics)。(Thus, the children still have a parent to collect their status and execution statistics.) 4.4 协作进程 在操作系统中并发执行的进程可能是独立进程或协作进程(cooperating process)。如果一个进程不会 影响系统中其它的进程,而且也不被其它进程影响,那么它是一个独立进程。很明显,不与其它进程共享 数据(临时的或长久的)的进程是独立进程。另一方面,如果一个进程会影响系统中其它的进程而且也被 影响,那么它是一个协作进程。无疑,与其它进程共享数据的进程是协作进程。 出于如下的几个原因,我们要提供一个允许进程协作的环境: l 信息共享:一些用户可能需要同样的信息(例如:一个共享文件),就必须要使他们能够同时访问这 些资源。 l 计算加速:如果我们有一个特殊任务需要更快的完成,那么必须将其分成若干子进程,这些子进程 并行执行。只有在系统拥有多重处理能力(如:多 CPU或多 I/O 通道)的情况下这种加速才能够实 现。 l 模块化:我们可能要以模块化设计构建系统,那么就要将系统功能分散到众多的独立进程和线程中 实现,正如我们在第三章所讨论的。 l 易用性(Convenience):甚至是单个用户也可能同时执行多个任务。例如,一个用户可能会同时编 辑、打印和编译程序。 协作进程的并行执行需要一些机制允许进程间通信(4.5节)并同步它们的活动(第七章)。 为了举例说明协同进程,考虑一下生产者—消费者问题( the producer -consumer problem),这是一个协 同进程的范例。一个生产者进程生产信息,而消费者进程消费这些信息。例如,一个打印程序生产字符供 打印机驱动程序消费。一个编译器生产汇编代码,汇编程序消费这些代码。反过来,汇编程序生产目标模 块,载入程序消费它们。 为了实现生产者进程和消费者进程的并行执行,我们必须要有一个有效的缓冲区,它可以由生产者装 入信息并由消费者取走信息。在(不定数量的)消费者消费条目的时候一个生产者能够生产条目。生产者 和消费者必须要同步,即消费者不能够消费一个尚未产出的条目。在这种情况下,消费者必须要等待该条 目产出。 无限长度缓冲区(unbounded-buffer)的生产者—消费者问题采用了没有实际容量限制的缓冲区。消费 者可能必须要等待新条目,但是生产者总是可以生产新条目。有限长度缓冲区(bounded-buffer)的生产者 —消费者问题采取了一个固定容量的缓冲区。这样,如果缓冲区空,消费者必须等待;如果缓冲区满,生 产者必须等待。 http://www.tulipsys.com 缓冲区或者由操作系统使用进程间通信(IPC)机制提供(4.5 节),或者由使用共享存储器的程序员 亲自编码实现。下面演示了一个在共享内存中实现的有边界缓冲区。生产者和消费者共享这如下这些变量: #define BUFFER_SIZE 10 typedef struct { . . . } item; item buffer [BUFFER_SIZE]; int in = 0; int out = 0; 共享缓冲区实现为一个循环队列,它有两个逻辑指针:in和 out。变量 in指向缓冲区里的下一个空闲 位置,out指向缓冲区里第一个满位置。当 in = out时,缓冲区为空;当 ((in + 1) % BUFFER_SIZE) = out时, 缓冲区满。 生产者和消费者进程的代码如下。生产者进程有一个局部变量 nextProduced,它存储生产的新条目: while (1){ /* produce an item in nextProduced */ while (((in + 1) % BUFFER_SIZE) = = out) ; /* do nothing */ buffer [in] = nextProduced; in = (in + 1) % BUFFER_SIZE; } 消费者进程有一个局部变量 nextConsumed,它存储要消费的条目: while (1) { while (in = = out) ; // do nothing nextConsumed = buffer [out]; out = (out + 1) % BUFFER_SIZE; /* consume the item in nextConsumed */ } 这种 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 允许缓冲区中同时最多有 BUFFER_SIZE – 1个条目。作为一个练习,请提供一种解决方案使缓冲 区中同时最多有 BUFFER_SIZE个条目。 在第七章中,我们讨论在共享存储器的环境下如何实现协作进程间的同步。 4.5 进程间通信 我们在 4.4 节讨论了协作进程如何在共享存储器环境下进行通信。这种方案需要这些进程共享一个共 同的缓冲池而且实现缓冲区的代码由应用程序程序员亲自完成。另一种方法是通过进程间通信(IPC)为 操作系统提供协作进程互相通信的机制。 IPC提供了一个无需共享地址空间就能实现进程通信以及同步进程活动的机制。在分布式环境中,IPC 尤其有用,因为这种环境下相互通信的进程驻留在通过网络连接的不同的计算机中。一个例子就是在环球 网上使用的聊天程序。 最好是通过消息传递系统提供 IPC,而且有很多种定义消息系统的方法。在这一节,我们会看到设计 消息传递系统所面临的不同问题。 4.5.1 消息传递系统 消息系统的功能是允许进程与其它的进程进行通信而不必借助共享数据。我们已经看到了消息传递在 微内核中的应用(3.5.3 节)。在这种方案下,服务作为普通的用户进程提供。更确切的说,服务在内核之 http://www.tulipsys.com 外。用户进程之间的通信通过传递消息完成。IPC至少提供了两种操作:send(message)和 receive(message)。 进程发送的消息可以是定长的也可以是变长的。如果只可以发送定长的消息,那么系统层的实现就很 简单。然而,这种限制增加了程序设计的难度。另一方面,变长的消息需要更复杂的系统层实现,但是程 序设计工作更简单。 如果进程 P和 Q要进行通信,那么它们必须能够互相发送和接收消息;二者之间必须要建立一条通信 链路。有多种方法可以实现这条链路。在这儿,我们并不关心链路的物理实现(如在第十五章中介绍的共 享内存、硬件总线或网络),而是要考虑它的逻辑实现。有如下几种用于逻辑实现和 send/receive操作的方 法: l 直接或间接通信 l 对称或不对称通信 l 自动或手动缓冲(Automatic or explicit buffering) l 发送拷贝或引用 l 定长消息或变长消息(Fixed-sized or variable-sized messages) 下面我们逐步着看一下这些消息系统类型。 4.5.2 命名 需要通信的进程必须要有一种方式来互相识别,这可以使用直接或间接通信方式。 4.5.2.1 直接通信 直接通信中,需要通信的每个进程都必须直接指明通信的接收方或发送方。在这种方式下,发送和接 收原语定义如下: l send(P, message) –发送一个消息给进程 P。 l receive (Q, message) –从进程Q中接收一个消息。 这种通信链路具有如下特点: l 每对需要通信的进程之间自动的建立一条链路。进程只需要知道彼此的标识符(identity)。 l 一个连接就只连接到这两个进程。 l 每对进程间只能够建立一条链路。(Exactly one link exists between each pair of processes.) 这种机制在寻址上对称。(This scheme exhibits symmetry in addressing);发送者和接收者进程都必须要 指明通信的另一方。这种机制的一个变种在寻址上采用了不对称的方式。(A variant of this scheme employs asymmetry in addressing.)只有发送者指明接收者;而接收者不需要指明发送者。在这种方式下,发送和接 收原语定义如下: l send(P, message) –发送一个消息给进程 P。 l receive (id, message) –从任意进程中接收一个消息;变量 id被联系到与之通信的进程的名称。 对称和不对称机制的缺点在于它限制了进程定义的模块化程度。(The disadvantage in both symmetric and asymmetric schemes is the limited modularity of the resulting process definitions.)更改一个进程的名称可 能必须要检查其它所有进程的定义。必须要发现所有对原名称的引用,以便于更换为新名称。从独立编译 角度来看,这种情形可不是希望看到的。 4.5.2.2 间接通信 间接通信中,消息的发送和接收通过信箱(或端口)进行。可以抽象的把信箱看成一个对象,进程可 以把消息放置其中也能从中取走。每个信箱都有一个唯一的标识符。在这种方式下,进程可以通过不同的 信箱与其它进程通信。两个进程只有共享一个信箱才可以进行通信。发送和接收原语定义如下: l send(A, message) –向信箱 A中发送一个消息。 l receive (A, message) –从信箱 A中接收一个消息。 这种通信链路具有如下特点: l 只有在两个进程间有一个共享信箱的情况下才能在二者之间建立一个链接。 l 一条链路可以连接两个或更多进程。 l 在每对通信进程之间可以同时存在多个不同的链路,每条链路对应一个信箱。 假设进程 P1、P2,和 P3 共享信箱 A,而且 P2和 P3正从 A中接收。那么谁将接收到 P1发送的消息呢? http://www.tulipsys.com 答案与我们选择的方案有关: l 允许一条链路最多连接两个进程。 l 同时最多允许一个进程执行接收操作。 l 允许系统任意选择进程来接收消息(就是说,P2或者 P3,但不能都是,将接收消息)。系统可能 会确定接受者。(The system may identify the receiver to the sender.) 一个信箱可能为一个进程或操作系统所有。如果信箱的所有者是一个进程(就是说,此信箱占据了该 进程的部分地址空间),那么我们就要区分所有者(唯一可以从这个信箱中接收消息)和用户(只能够向 这个信箱中发送消息)。因为每个信箱有一个唯一的所有者,所以谁可以从此信箱中接收消息就很明确了。 当一个拥有一个信箱的进程终止时,信箱也要消失。随后,向这个信箱发送消息的进程都会被告知该信箱 已经不存在了。 另一方面,操作系统拥有的一个信箱是独立的且不会依附于任何进程。那么操作系统必须要提供一种 机制以允许一个进程做如下的工作: l 创建一个新信箱。 l 通过这个信箱发送和接收消息。 l 删除一个信箱。 创建了一个新信箱的进程默认为该信箱的所有者。最初,所有者是唯一能够从此信箱中接收消息的进 程。然而,可以通过系统调用将(信箱的)所有权和接收权交给其它进程。当然,这会造成每个信箱有多 个接收者的情况。 4.5.3 同步 进程通过调用发送和接收原语来实现通信。有不同的方法来实现每个原语。消息传递可能是有阻塞 (blocking)或无阻塞(nonblocking)——也被称为同步(synchronous)和异步(asynchronous)。 l 发送进程阻塞: 发送进程被阻塞,直到消息被接收进程或信箱接收。 l 发送进程不阻塞:发送进程发送消息并恢复执行。 l 接收进程阻塞:接收进程被阻塞,直到一个消息有效。 l 接收进程不阻塞:接收进程获取一个有效消息或空消息。 发送和接收的方式可能会有不同的组合。发送和接收都是有阻塞的方式时,两个进程会在某个地方会 合(也就同步了)。(When both the send and receive are blocking, we have a rendezvous between the sender and the receiver.) 4.5.4 缓冲(Buffering) 不管通信是直接的还是间接的,通信进程交换的消息都是驻留在一个临时队列中。这样的队列有三种 基本的实现方式: l 零长度(Zero capacity):队列的最大长度是 0;从而不能有任何消息在链表中等待。在这种情况 下,发送者必须阻塞,直到接收者接收到消息。 l 限定长度(Bounded capacity):对列有限定的长度 n;从而最多允许 n个消息驻留其中。如果当 一个发送消息时对列未满,那么消息就会被放置在对列中稍后的位置(拷贝消息或保留指向消息 的指针),而且发送者可以继续执行而无需等待。然而,链表的容量有限。如果链表满,那么发 送者必须阻塞,直到对列中出现有效空间。 l 无限长度(Unbounded capacity):对列的潜在长度无限;从而可以有任意数目的消息在对列中等 待。发送者不会阻塞。 零缓冲区的情况有时被称为无缓冲区消息系统;其它的两种情况被称为自动缓冲。(The zero-capacity case is sometimes referred to as a message system with no buffering; the other cases are referred to as automatic buffering. ) 4.5.5 实例:Mach 作为一个基于消息的操作系统的例子,考虑一下由 Carnegie Mellon大学开发的 Mach操作系统。Mach 内核支持多任务的创建和销毁,这与进程类似,但是拥有多道控制执行序列。(The Mach kernel supports the creation and destruction of multiple tasks, which are similar to processes but have multiple threads of control.) http://www.tulipsys.com Mach 中的大部分通信(包括大部分系统调用和所有的任务间信息)通过消息实现。消息被发送到信箱并 从中接收,信箱在 Mach中被称为端口。 甚至系统调用也通过消息实现。当(每个)任务创建时,两个专门的信箱(Kernel信箱和 Notify信箱) 也同时创建。内核通过 Kernel信箱与任务(task)通信。内核发送事件发生的 通知 关于发布提成方案的通知关于xx通知关于成立公司筹建组的通知关于红头文件的使用公开通知关于计发全勤奖的通知 到 Notify端口。消息传 递只需要三个系统调用。msg_send 调用发送一个消息到信箱中。通过 msg_receive 接收一个消息。通过 msg_rpc 执行远程过程调用(RPC),发送一个消息并等待发送者返回的信息。这样,RPC很像是一个典型 的子进程调用,但是能够工作在(不同的)系统之间。 port_allocate 系统调用创建一个新信箱并为其消息对列分配空间。消息队列的最大容量为八个消息。 创建信箱的任务是该信箱的所有者。所有者也获得访问信箱的权限。每次只有一个任务能够拥有一个信箱 或从一个信箱中接收信息的权力,但是如果需要,可以把权力移交给其它的任务。 信箱最初有一个空消息队列。当消息被发送到信箱时,它被拷贝到信箱中。所有的消息拥有同样的优 先权。Mach以先进先出(FIFO)方式来维护来自同一进程的多个消息,但是并不保证有一个绝对的次序。 例如,来自两个发送者的每个消息在队列中的次序可能是任意的。 消息包括一个固定长度的消息头,随后是一个可变长度的数据段。消息头包含了消息的长度和两个信 箱的名称。当一个消息被发送时,一个信箱的名称是发送此消息的信箱的名称。通常,发送线程期望获得 一个回复;发送者的信箱名称被传送给接收任务,这可能作为一个“返回地址”用于返回消息。 一个消息中的可变部分是一个数据条目列表。列表中的每个实体有(自己的)类型、体积(size)和 数值(value)。在消息中指明对象的类型是很重要的,因为操作系统定义的对象(如所有权或接收访问权、 任务状态和存储段)可能在消息中被发送。 发送和接收操作本身是很灵活的。例如,当一个消息被发送到一个信箱时,该信箱可能是满的。如果 这个信箱未满,那么消息被拷贝到信箱中,发送线程继续执行。如果信箱满,那么发送线程有如下四种选 择: 1. 无限等待,直到信箱中出现空位置。 2. 最多等待 n毫秒。 3. 从不等待,立即返回。 4. 临时缓存一个消息。可以把消息交给操作系统保存,即使目的信箱满。当消息被发送给信箱时, 一个通知消息会返回给发送者;only one such message to a full mailbox can be pending at any time for a given sending thread.(这句话不太理解) 最后的选项适用于服务器任务,如一个线性打印机驱动程序。在完成一个请求之后,这些任务可能需要发 送一个答复给请求服务的任务,但是也必须要继续处理其它的服务请求,即使客户端回复信箱满。 接收操作必须要指明由哪个信箱或信箱集接收消息。一个信箱集是一个信箱的集合,它是任务声明的, 可以根据任务的意图组织在一起并像一个信箱那样对待。任务中的线程能够从一个信箱或信箱集中接收信 息,而任务拥有对该信箱或信箱集的访问权限。port_status 系统调用返回指定信箱中的消息数量。接收操 作以如下的某种方式尝试接收: 1. 信箱集中的任意信箱 2. 某一具体的(指定的)信箱 如果没有消息等待接收,那么接收线程可能会等待、最多等待 n毫秒或不等待。 虽然 Mach 系统是专为分布式系统(在第十五章到十七章讨论)设计的,但是 Mach 也适用于单处理 机系统。消息系统的主要问题在于消息的拷贝,首先从发送者拷贝到信箱,再从信箱拷贝到接收者,这通 常会造成系统的低性能。Mach 消息系统通过使用虚拟内存管理技术(第十章)来避免两次拷贝。其本质 就是 Mach将包含着发送者的消息的地址空间映象到接收者的地址空间。消息本身实际上没有被拷贝。这 种消息管理技术很大程度上提升了性能,但是只能用于系统内的消息。在我们的网站中有额外的一章来讨 论 Mach操作系统(http://www. bell-labs.com/topic/books/os -book)。 4.5.6 实例:Windows 2000 Windows 2000 操作系统是一个现代操作系统设计的例子,它采用了模块化设计来增加系统功能并减少 实现新特征所需的时间。Windows 2000 提供了对多操作环境或子系统的支持,应用程序可以通过消息传递 http://www.tulipsys.com 机制进行通信。应用程序可被视为 Windows 2000子系统服务器的客户端。 Windows 2000 中的消息传递机制被称为本地过程调用(LPC)。在 Windows 2000中,LPC在处于同 一台机器上的两个进程间通信。这与广泛应用的 RPC机制很相似,但是它专门针对 Windows 2000进行了 优化。如同 Mach,Windows 2000利用一个端口对象来建立和维护两个进程间的连接。客户端想调用子系 统的话,需要一个通信信道。信道由端口对象提供,而且不会遗传下去。调用子系统的客户端需要一个通 信通道,该通道由端口对象提供,而且不能继承。(Every client that calls a subsystem needs a communication channel, which is provided by a port object and is never inherited.)Windows 2000使用了两类端口:连接端口 (connection port)和通信端口(communication port)。它们实际上是相同的,但是根据不同的使用方式赋 予了不同的名称。连接端口是指定的对象(named object),对所有的进程可视;为应用程序提供了建立通 信通道的方法(第二十一章)。这种通信的工作如下: l 客户端打开一个子系统的连接端口对象的句柄(The client opens a handle to the subsystem's connection port object.) l 客户端发送一个连接请求。 l 服务器创建两个私有通信端口,并将其中一个端口的句柄返回给客户端。(The server creates two private communication ports, and returns the handle to one of them to the client.) l 客户端和服务器使用相应的端口发送消息或回调,并且监听有没有回复。(The client and server use the corresponding port handle to send messages or callbacks and to listen for replies.) Win2000支持三种消息传递的技术,一个端口具体使用哪一种由客户端在建立通信频道的时候就指出 来。Windows 2000采用了三种消息传递技术,当端口建立通道时才具体指明使用哪种技术。(Windows 2000 uses three types of message-passing techniques over a port that the client specifies when it establishes the channel.)最简单的一种方式是使用端口的消息队列作为中间存储器,消息从一个进程拷贝到其它进程,这 种方式用于传递短消息(small message)。在这种方式下,消息的最大长度是 256字节。 如果客户端需要发送更大的消息,他可以通过一个 section object(或共享存储器)。当客户端建立通道 的时候,它必须决定是否需要发送一个大的消息(large message)。如果客户端认为自己需要发送大消息, 那么它就请求创建一个 section object。同样,如果服务器认为回复很大,它就创建一个 section object。发 送一个包含了关于 section object指针和体积信息的短消息,以此来使用 section object。(Likewise, if the server decides that replies will be large, it creates a section object. So that the section object can be used, a small message is sent that contains a pointer and size information about that section object.)这种方法比第一种更为复 杂,但是它避免了数据拷贝。在两种情况下,在客户端或服务器不能够立即响应请求时可以使用回调 (callback)机制。回调机制允许进行异步消息处理。 4.6 客户端/服务器系统中的通信 用户常常需要访问放置在服务器上的数据。例如,一个用户可能想要知道在服务器 A中的一个文件的 行数、字数和字符数。那么远程服务器 A处理这个请求,它访问这个文件,计算所需的结果,最终将实际 的数据返回给用户。 4.6.1 套接字 套接字被定义为通信端点。通过网络通信的两个进程使用两个套接字——一个进程一个。socket通过 IP 地址和端口号识别。(A socket is identified of an IP address concatenated with a port number.)通常,套接字 使用客户端/服务器结构。服务器监听指定的端口来等待接收客户端的请求。一旦接收到一个请求,服务 器会接受来自客户端套接字的连接请求并完成该连接。 服务器监听通用端口(telnet服务器监听端口 23,ftp服务器监听端口 21,web(或 http)服务器监听 端口 80)实现具体的服务(如 telnet、ftp和 http)。序号小于 1024的所有端口是通用的;我们可以利用它 们实现 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 的服务。 当一个客户端进程发起一个连接请求时,主机会为它分配一个端口。这个端口是大于 1024 的任意整 数。例如,如果一个 IP 地址为 146.86.5.20 的主机 X 上的一个客户端进程想要与一个地址为 161.25.19.8 的 web 服务器(它监听端口 80
本文档为【操作系统概念第四章 进程】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_748777
暂无简介~
格式:pdf
大小:986KB
软件:PDF阅读器
页数:22
分类:工学
上传时间:2011-05-18
浏览量:23