通过讨论所谓的临界区问题(critical-section problem),让我们开始思考进程同步。考虑一个由n个进程{P 0 , P 1 ,..., P n−1 }组成的系统。每个进程都有一段称为临界区(critical section)的代码,进程会在其中更改公共变量、更新表、编写文件等等。该系统的重要特性是,当一个进程在其临界区(critical section)执行时,不允许其他进程在其临界区(critical section)执行。也就是说,没有两个进程可以同时在它们的临界区(critical section)执行。临界区问题(critical-section problem)是设计一个进程可以用来进行协作的协议。每个进程必须请求允许进入其临界区(critical section)。实现此请求的代码段是入口区(entry section)临界区(critical section)之后则是出口区(exit section)。其余的代码是剩余区(remainder section)。典型的进程Pi的一般结构如图5.1所示。入口区和出口区被封闭在方框中,以突出这些重要的代码段。

临界区问题(critical-section problem)的解决方案必须满足以下三个要求:

  1. 互斥锁(Mutual exclusion):如果进程P在它的临界区(critical section)执行,那么没有其他进程可以在它们的临界区(critical section)没中执行。
  2. Progress:如果一个进程正在它的临界区(critical section)中执行,并且有很多其他的进程也希望进入他们的临界区(critical section)。然后,只有那些没有在其剩余区(remainder section)中执行的进程才能参与决定哪一个将进入它的临界区(critical section),而这个选择不能被无限期延迟。
  3. 限界等待(Bounded waiting):在一个进程发出请求进入其临界区(critical section)并在该请求被确认之前,其他进程被允许进入其临界区(critical section)的次数有一个范围或限制。

我们假设每个进程都以非零的速度执行。然而,我们不能对n个进程的相对速度做任何假设。

在一个给定的时间点上,可能会有许多内核模式的进程在操作系统中处于活动状态。因此,实现操作系统(内核代码)的代码会受到多个可能的竞态条件(race condition)的影响。以一个内核数据结构为例,它维护系统中所有打开的文件的列表。当打开或关闭新文件时,必须修改此列表(将文件添加到列表中或将其从列表中删除)。如果两个进程同时打开文件,则该列表的单独更新可能导致竞态条件(race condition)。其他可能出现竞态条件的内核数据结构包括维护内存分配、维护进程列表和中断处理的结构。这取决于内核开发人员,以确保操作系统不受这种竞争条件的影响。

有两种通用方法用于处理操作系统中的临界区(critical section):抢占式内核(preemptive kernels)非抢占式内核(nonpreemptive kernels)抢占式内核允许进程在内核模式运行时被抢占。非抢占内核不允许在内核模式中运行的进程被抢占;内核模式下,进程将一直运行,直到它退出内核模式、阻塞或自愿让出CPU控制。

显然,一个非抢占式的内核基本上不受内核数据结构的竞争条件的影响,因为只有一个进程在内核中处于活动状态。但是对于抢占内核,则是不同的,所以必须仔细设计,以确保共享的内核数据不受竞态条件(race condition)的影响。对于SMP("对称多处理"(Symmetrical Multi-Processing))架构来说,抢占式内核尤其困难,因为在这些环境中,两个内核模式进程可以同时在不同的处理器上运行。

那么,为什么有人会赞成抢占式内核(preemptive kernels)而不是非抢占式内核(nonpreemptive kernels)呢?抢占式内核(preemptive kernels)会更有响应性,因为在将处理器交付给其他waiting状态的进程之前,内核模式下的进程运行任意周期长的的风险更小[注:这是原文翻译,意思就是在处理器叫控制权交给下一个进程之前,当前内核模式运行的进程一般不会占用很久]。(当然,通过设计不以这种方式运行的内核代码,这种风险也可以最小化。)此外,抢占式内核更适合于实时编程,因为它将允许实时进程抢占当前内核中正在运行的进程。在本章后面,我们将探讨各种操作系统。

results matching ""

    No results matching ""