操作系统学习笔记

第一章 操作系统引论

1.1 操作系统的目标和作用

1.1.1 操作系统的目标
  1. 有效性

操作系统的有效性可包含如下两方面的含意:

(1) 提高系统资源利用率。配置了 OS 之后,可使 CPU 和 I/O 设备由于能保持忙碌状态而得到有效的利用,且可使内存和外存中存放的数据因有序而节省了存储空间。

(2) 提高系统的吞吐量。操作系统还可以通过合理地组织计算机的工作流程,而进一步改善资源的利用率,加速程序的运行,缩短程序的运行周期,从而提高系统的吞吐量。

  1. 方便性

配置 OS 后可使计算机系统更容易使用。

  1. 可扩充性

OS 必须具有很好的可扩充性,方能适应计算机硬件、体系结构以及应用发展的要求。

  1. 开放性

为使来自不同厂家的计算机和设备能通过网络加以集成化,并能正确、有效地协同工作,实现应用的可移植性和互操作性,要求操作系统必须提供统一的开放环境,进而要求 OS 具有开放性。

开放性是指系统能遵循世界标准规范,特别是遵循开放系统互连(OSI)国际标准。凡遵循国际标准所开发的硬件和软件,均能彼此兼容,可方便地实现互连。

1.1.2 操作系统的作用
  1. OS 作为用户与计算机硬件系统之间的接口

OS 作为用户与计算机硬件系统之间接口的含义是:OS 处于用户与计算机硬件系统之间,用户通过 OS 来使用计算机系统。或者说,用户在 OS 帮助下,能够方便、快捷、安全、可靠地操纵计算机硬件和运行自己的程序。

用户可通过以下三种方式使用计算机:

(1) 命令方式。这是指由 OS 提供了一组联机命令接口,以允许用户通过键盘输入有关命令来取得操作系统的服务,并控制用户程序的运行。

(2) 系统调用方式。OS 提供了一组系统调用,用户可在自己的应用程序中通过相应的系统调用,来实现与操作系统的通信,并取得它的服务。

(3) 图形、窗口方式。这是当前使用最为方便、最为广泛的接口,它允许用户通过屏幕上的窗口和图标来实现与操作系统的通信,并取得它的服务。

  1. OS 作为计算机系统资源的管理者

在一个计算机系统中,通常都含有各种各样的硬件和软件资源。归纳起来可将资源分为四类:处理器、存储器、I/O 设备以及信息(数据和程序)。

(1) 处理机管理,用于分配和控制处理机;

(2) 存储器管理,主要负责内存的分配与回收;

(3) I/O 设备管理,负责 I/O 设备的分配与操纵;

(4) 文件管理,负责文件的存取、共享和保护。

  1. OS 实现了对计算机资源的抽象

OS 是铺设在计算机硬件上的多层系统软件,它们不仅增强了系统的功能,而且还隐藏了对硬件操作的细节,由它们实现了对计算机硬件操作的多个层次的抽象。

1.2 操作系统的发展过程

1.2.1 无操作系统的计算机系统
1.2.2 单道批处理系统
  1. 单道批处理系统的处理过程

其自动处理过程是:首先,由监督程序将磁带上的第一个作业装入内存,并把运行控制权交给该作业。当该作业处理完成时,又把控制权交还给监督程序,再由监督程序把磁带(盘)上的第二个作业调入内存。计算机系统就这样自动地一个作业一个作业地进行处理,直至磁带(盘)上的所有作业全部完成,这样便形成了早期的批处理系统。由于系统对作业的处理都是成批地进行的,且在内存中始终只保持一道作业,故称此系统为单道批处理系统(Simple Batch Processing System)。

  1. 单道批处理系统的特征

(1) 自动性。在顺利情况下,在磁带上的一批作业能自动地逐个地依次运行,而无需人工预。

(2) 顺序性。磁带上的各道作业是顺序地进入内存,各道作业的完成顺序与它们进入内存的顺序,在正常情况下应完全相同,亦即先调入内存的作业先完成。

(3) 单道性。内存中仅有一道程序运行,即监督程序每次从磁带上只调入一道程序进入内存运行,当该程序完成或发生异常情况时,才换入其后继程序进入内存运行。

1.2.3 多道批处理系统
  1. 多道批处理系统的基本概念

在引入多道程序设计技术后,由于同时在内存中装有若干道程序,并使它们交替地运行,这样,当正在运行的程序因 I/O 而暂停执行时,系统可调度另一道程序运行,从而保持了 CPU 处于忙碌状态。

宏观上并行:同时进入系统的多道程序都处于运行过程中,即它们先后开始了各自的运行,但都未运行完毕。

微观上串行:内存中的多道程序轮流占有 CPU,交替执行。

  1. 多道批处理系统的优点

(1) 提高 CPU 的利用率。

(2) 可提高内存和 I/O 设备利用率。许在内存中装入多道程序,并允许它们并发执行,则无疑会大大提高内存和 I/O 设备的利用率。

(3) 增加系统吞吐量。在保持 CPU、I/O 设备不断忙碌的同时,也必然会大幅度地提高系统的吞吐量,从而降低作业加工所需的费用。

  1. 多道批处理系统的优点

(1) 平均周转时间长。在批处理系统中,由于作业要排队,依次进行处理,因而作业的周转时间较长,通常需几个小时,甚至几天

(2) 无交互能力。用户一旦把作业提交给系统后,直至作业完成,用户都不能与自己的作业进行交互,这对修改和调试程序是极不方便的。

1.2.4 分时系统
  1. 分时系统的概念

在操作系统中釆用分时技术就形成了分时系统。所谓分时技术就是把处理器的运行时间分成很短的时间片,按时间片轮流把处理器分配给各联机作业使用。若某个作业在分配给它的时间片内不能完成其计算,则该作业暂时停止运行,把处理器让给其他作业使用,等待下一轮再继续运行。由于计算机速度很快,作业运行轮转得很快,给每个用户的感觉好像是自己独占一台计算机。

  1. 分时系统的特征

(1) 多路性。允许在一台主机上同时联接多台联机终端,系统按分时原则为每个用户服务。宏观上,是多个用户同时工作,共享系统资源;而微观上,则是每个用户作业轮流运行一个时间片。多路性即同时性,它提高了资源利用率,降低了使用费用,从而促进了计算机更广泛的应用。

(2) 独立性。每个用户各占一个终端,彼此独立操作,互不干扰。因此,用户所感觉到的,就像是他一人独占主机。

(3) 及时性。用户的请求能在很短的时间内获得响应。此时间间隔是以人们所能接受的等待时间来确定的,通常仅为 1~3 秒钟。

(4) 交互性。用户可通过终端与系统进行广泛的人机对话。其广泛性表现在:用户可以请求系统提供多方面的服务,如文件编辑、数据处理和资源共享等。

1.2.5 实时系统

所谓“实时”,是表示“及时”,而实时系统(Real Time System)是指系统能及时(或即时)
响应外部事件的请求,在规定的时间内完成对该事件的处理,并控制所有实时任务协调一
致地运行。

1.2.6 微机操作系统的发展

配置在微型机上的操作系统称为微机操作系统。

  1. 单用户单任务操作系统

单用户单任务操作系统的含义是,只允许一个用户上机,且只允许用户程序作为一个任务运行。最有代表性的单用户单任务微机操作系统是 CP/M 和 MS-DOS。

  1. 单用户多任务操作系统

单用户多任务操作系统的含义是,只允许一个用户上机,但允许用户把程序分为若干个任务,使它们并发执行,从而有效地改善了系统的性能。目前在 32 位微机上配置的操作系统基本上都是单用户多任务操作系统,其中最有代表性的是由微软公司推出的 Windows。

  1. 多用户多任务操作系统

多用户多任务操作系统的含义是,允许多个用户通过各自的终端使用同一台机器,共享主机系统中的各种资源,而每个用户程序又可进一步分为几个任务,使它们能并发执行,从而可进一步提高资源利用率和系统吞吐量。

其中最有代表性的是 UNIX OS。现在最有影响的两个能运行在微机上的 UNIX 操作系统的变型是 Solaris OS 和 Linux OS。

1.3 操作系统的基本特性

1.3.1 并发性
  1. 并行与并发

并行性和并发性(Concurrence)是既相似又有区别的两个概念,并行性是指两个或多个事件在同一时刻发生;而并发性是指两个或多个事件在同一时间间隔内发生。

在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。

倘若在计算机系统中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可同时执行。

  1. 引入进程

应当指出,通常的程序是静态实体(Passive Entity),在多道程序系统中,它们是不能独立运行的,更不能和其它程序并发执行。在操作系统中引入进程的目的,就是为了使多个程序能并发执行。

为使多个程序能并发执行,系统必须分别为每个程序建立进程(Process)。简单说来,进程是指在系统中能独立运行并作为资源分配的基本单位,它是由一组机器指令、数据和堆栈等组成的,是一个能独立运行的活动实体。多个进程之间可以并发执行和交换信息。一个进程在运行时需要一定的资源,如 CPU、存储空间及 I/O 设备等。

  1. 引入线程

通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源。在引入线程的 OS 中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位。

1.3.2 共享性

在操作系统环境下,所谓共享(Sharing),是指系统中的资源可供内存中多个并发执行的进程(线程)共同使用,相应地,把这种资源共同使用称为资源共享,或称为资源复用。

  1. 互斥共享方式

系统中的某些资源,如打印机、磁带机,虽然它们可以提供给多个进程(线程)使用,但为使所打印或记录的结果不致造成混淆,应规定在一段时间内只允许一个进程(线程)访问该资源。为此,系统中应建立一种机制,以保证对这类资源的互斥访问。

为此,系统中应建立一种机制,以保证对这类资源的互斥访问。当一个进程 A 要访问某资源时,必须先提出请求。如果此时该资源空闲,系统便可将之分配给请求进程 A 使用。此后若再有其它进程也要访问该资源时(只要 A 未用完),则必须等待。仅当 A 进程访问完并释放该资源后,才允许另一进程对该资源进行访问。

我们把这种资源共享方式称为互斥式共享,而把在一段时间内只允许一个进程访问的资源称为临界资源或独占资源。计算机系统中的大多数物理设备,以及某些软件中所用的栈、变量和表格,都属于临界资源,它们要求被互斥地共享。为此,在系统中必需配置某种机制来保证诸进程互斥地使用独占资源。

临界资源是定义在共享资源上的,临界资源一定是共享资源。

  1. 同时共享方式

系统中还有另一类资源,允许在一段时间内由多个进程“同时”对它们进行访问。这里所谓的“同时”,在单处理机环境下往往是宏观上的,而在微观上,这些进程可能是交替地对该资源进行访问。典型的可供多个进程“同时”访问的资源是磁盘设备,一些用重入码编写的文件也可以被“同时”共享,即若干个用户同时访问该文件。

虚拟性
  1. 时分复用技术

在虚拟处理机技术中,利用多道程序设计技术,为每道程序建立一个进程,让多道程序并发地执行,以此来分时使用一台处理机。此时,虽然系统中只有一台处理机,但它却能同时为多个用户服务,使每个终端用户都认为是有一个处理机在专门为他服务。

  1. 空分复用技术

如果说时分复用技术是利用处理机的空闲时间来运行其它的程序,使处理机的利用率得以提高,那么空分复用则是利用存储器的空闲空间来存放其它的程序,以提高内存的利用率。

1.3.4 异步性

进程是以人们不可预知的速度向前推进,此即进程的异步性(Asynchronism)。

1.4 操作系统的主要功能

1.4.1 处理机管理功能
  1. 进程控制

进程控制的主要功能是为作业创建进程,撤消已结束的进程,以及控制进程在运行过程中的状态转换。在现代 OS 中,进程控制还应具有为一个进程创建若干个线程的功能和撤消(终止)已完成任务的线程的功能。

  1. 进程同步

前已述及,进程是以异步方式运行的,并以人们不可预知的速度向前推进。为使多个进程能有条不紊地运行,系统中必须设置进程同步机制。

(1) 进程互斥方式。这是指诸进程(线程)在对临界资源进行访问时,应采用互斥方式;

(2) 进程同步方式。这是指在相互合作去完成共同任务的诸进程(线程)间,由同步机构对它们的执行次序加以协调。

  1. 进程通信

当相互合作的进程(线程)处于同一计算机系统时,通常在它们之间是采用直接通信方式,即由源进程利用发送命令直接将消息(Message)挂到目标进程的消息队列上,以后由目标进程利用接收命令从其消息队列中取出消息。

  1. 调度

在后备队列上等待的每个作业都需经过调度才能执行。在传统的操作系统中,包括作业调度和进程调度两步。

1.4.2 存储器管理功能
  1. 内存分配

内存分配的主要任务是为每道程序分配内存空间,使它们“各得其所”;提高存储器的利用率,以减少不可用的内存空间;允许正在运行的程序申请附加的内存空间,以适应程序和数据动态增长的需要。

  1. 内存保护

内存保护的主要任务是确保每道用户程序都只在自己的内存空间内运行,彼此互不干扰;绝不允许用户程序访问操作系统的程序和数据;也不允许用户程序转移到非共享的其它用户程序中去执行。

  1. 地址映射

为使程序能正确运行,存储器管理必须提供地址映射功能,以将地址空间中的逻辑地址转换为内存空间中与之对应的物理地址。该功能应在硬件的支持下完成。

  1. 内存扩充

存储器管理中的内存扩充任务并非是去扩大物理内存的容量,而是借助于虚拟存储技术,从逻辑上去扩充内存容量,使用户所感觉到的内存容量比实际内存容量大得多,以便让更多的用户程序并发运行。

(1) 请求调入功能。允许在装入一部分用户程序和数据的情况下,便能启动该程序运行。在程序运行过程中,若发现要继续运行时所需的程序和数据尚未装入内存,可向 OS 发出请求,由 OS 从磁盘中将所需部分调入内存,以便继续运行。

(2) 置换功能。若发现在内存中已无足够的空间来装入需要调入的程序和数据时,系统应能将内存中的一部分暂时不用的程序和数据调至盘上,以腾出内存空间,然后再将所需调入的部分装入内存。

1.4.3 设备管理功能

设备管理用于管理计算机系统中所有的外围设备,而设备管理的主要任务是:完成用户进程提出的 I/O 请求;为用户进程分配其所需的 I/O 设备;提高 CPU 和 I/O 设备的利用率;提高I/O 速度;方便用户使用 I/O 设备。

  1. 缓冲功能

CPU 运行的高速性和 I/O 低速性间的矛盾自计算机诞生时起便已存在了。如果在 I/O 设备和 CPU之间引入缓冲,则可有效地缓和 CPU 与 I/O 设备速度不匹配的矛盾,提高 CPU 的利用率,进而提高系统吞吐量。提高 CPU 与设备之间的并行程度。

  1. 设备分配

设备分配的基本任务是根据用户进程的 I/O 请求、系统的现有资源情况以及按照某种设备的分配策略,为之分配其所需的设备。

  1. 设备处理

设备处理程序又称为设备驱动程序。其基本任务是用于实现 CPU 和设备控制器之间的通信,即由 CPU 向设备控制器发出 I/O 命令,要求它完成指定的 I/O 操作;反之,由 CPU 接收从控制器发来的中断请求,并给予迅速的响应和相应的处理。

1.4.4 文件管理功能
  1. 文件存储空间的管理

系统应设置相应的数据结构,用于记录文件存储空间的使用情况,以供分配存储空间时参考;系统还应具有对存储空间进行分配和回收的功能。为了提高存储空间的利用率,对存储空间的分配,通常是采用离散分配方式,以减少外存零头,并以盘块为基本分配单位。盘块的大小通常为 1~8 KB。

  1. 目录管理

为了使用户能方便地在外存上找到自己所需的文件,通常由系统为每个文件建立一个目录项。目录项包括文件名、文件属性、文件在磁盘上的物理位置等。由若干个目录项又可构成一个目录文件。其次,目录管理还应能实现文件共享,这样,只须在外存上保留一份该共享文件的副本。此外,还应能提供快速的目录查询手段,以提高对文件的检索速度。

  1. 文件的读/写管理和保护
1.4.5 操作系统与用户之间的接口
  1. 用户接口

它是提供给用户使用的接口,用户可通过该接口取得操作系统的服务;

  1. 程序接口

它是提供给程序员在编程时使用的接口,是用户程序取得操作系统服务的惟一途径。

1.5

1.5.1 微内核 OS 结构
  1. 微内核操作系统的优点

(1) 提高了系统的可扩展性

(2) 增强了系统的可靠性

(3) 可移植性

(4) 提供了对分布式系统的支持

(5) 融入了面向对象技术

  1. 微内核操作系统存在的问题

微内核 OS 的运行效率有所降低。效率降低的最主要的原因是,在完成一次客户对 OS 提出的服务请求时,需要利用消息实现多次交互和进行用户/内核模式及上下文的多次切换。

第二章 进程管理

2.1 进程的基本概念

2.1.1 程序的顺序执行及其特征
  1. 程序顺序执行时的特征

(1) 顺序性:处理机的操作严格按照程序所规定的顺序执行,即每一操作必须在上一个操作结束之后开始。

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

(3) 可再现性:只要程序执行时的环境和初始条件相同,当程序重复执行时,不论它是从头到尾不停顿地执行,还是“停停走走”地执行,都将获得相同的结果。

2.1.2 程序的并发执行及其特征
  1. 程序的并发执行时的特征

(1) 间断性:程序在并发执行时,由于它们共享系统资源,以及为完成同一项任务而相互合作,致使在这些并发执行的程序之间,形成了相互制约的关系。

(2) 失去封闭性:程序在并发执行时,是多个程序共享系统中的各种资源,因而这些资源的状态将由多个程序来改变,致使程序的运行失去了封闭性。这样,某程序在执行时,必然会受到其它程序的影响。例如,当处理机这一资源已被某个程序占有时,另一程序必须等待。

(3) 不可再现性:程序在并发执行时,由于失去了封闭性,也将导致其再失去可再现性。程序经过多次执行后,虽然它们执行时的环境和初始条件相同,但得到的结果却各不相同。

2.1.3 进程的特征与状态
  1. 进程的特征和定义

为使程序能并发执行,且为了对并发执行的程序加以描述和控制,人们引入了“进程”的概念。下面对进程的特征加以描述。

(1) 结构特征:

通常的程序是不能并发执行的。为使程序(含数据)能独立运行,应为之配置一进程控制块,即 PCB(Process Control Block);而由程序段、相关的数据段和 PCB三部分便构成了进程实体。在早期的 UNIX 版本中,把这三部分总称为“进程映像”。值得指出的是,在许多情况下所说的进程,实际上是指进程实体,例如,所谓创建进程,实质上是创建进程实体中的 PCB;而撤消进程,实质上是撤消进程的 PCB。

(2) 动态性:

进程的实质是进程实体的一次执行过程,因此,动态性是进程的最基本的特征。动态性还表现在:“它由创建而产生,由调度而执行,由撤消而消亡”。可见,进程实体有一定的生命期,而程序则只是一组有序指令的集合,并存放于某种介质上,其本身并不具有运动的含义,因而是静态的。

(3) 并发性:

这是指多个进程实体同存于内存中,且能在一段时间内同时运行。并发性是进程的重要特征,同时也成为 OS 的重要特征。引入进程的目的也正是为了使其进程实体能和其它进程实体并发执行;而程序(没有建立 PCB)是不能并发执行的。

(4) 独立性:

在传统的 OS 中,独立性是指进程实体是一个能独立运行、独立分配资源和独立接受调度的基本单位。凡未建立 PCB 的程序都不能作为一个独立的单位参与运行。

(5) 异步性:

这是指进程按各自独立的、 不可预知的速度向前推进,或说进程实体按异步方式运行。

现在我们再来讨论进程的定义。曾有许多人从不同的角度对进程下过定义,其中较典
型的进程定义有:

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

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

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

在引入了进程实体的概念后,我们可以把传统 OS 中的进程定义为:“进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位”。

  1. 进程的三种基本状态

(1) 就绪(ready)状态:

当进程已分配到除 CPU 以外的所有必要资源后,只要再获得 CPU,便可立即执行,进程这时的状态称为就绪状态。在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。

(2) 执行状态:

进程已获得 CPU,其程序正在执行。在单处理机系统中,只有一个进程处于执行状态;在多处理机系统中,则有多个进程处于执行状态。

(3) 阻塞状态:

正在执行的进程由于发生某事件而暂时无法继续执行时,便放弃处理机而处于暂停状态,亦即进程的执行受到阻塞,把这种暂停状态称为阻塞状态,有时也称为等待状态或封锁状态。致使进程阻塞的典型事件有:请求 I/O,申请缓冲空间等。通常将这种处于阻塞状态的进程也排成一个队列。有的系统则根据阻塞原因的不同而把处于阻塞状态的进程排成多个队列。

处于就绪状态的进程,在调度程序为之分配了处理机之后,该进程便可执行,相应地,它就由就绪状态转变为执行状态。正在执行的进程也称为当前进程,如果因分配给它的时间片已完而被暂停执行时,该进程便由执行状态又回复到就绪状态;如果因发生某事件而使进程的执行受阻(例如,进程请求访问某临界资源,而该资源正被其它进程访问时),使之无法继续执行,该进程将由执行状态转变为阻塞状态。图 2-5 示出了进程的三种基本状态以及各状态之间的转换关系。

  1. 挂起状态

在引入挂起状态后,又将增加从挂起状态(又称为静止状态)到非挂起状态(又称为活动状态)的转换;或者相反。可有以下几种情况:

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

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

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

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

  1. 创建状态和终止状态

(1) 创建状态:创建一个进程一般要通过两个步骤:首先,为一个新进程创建 PCB,并填写必要的管理信息;

其次,把该进程转入就绪状态并插入就绪队列之中。

当一个新进程被创建时,系统已为其分配了 PCB,填写了进程标识等信息,但由于该进程所必需的资源或其它信息,如主存资源尚未分配等,一般而言,此时的进程已拥有了自己的 PCB,但进程自身还未进入主存,即创建工作尚未完成,进程还不能被调度运行,其所处的状态就是创建状态。

(2) 终止状态:进程的终止也要通过两个步骤:首先等待操作系统进行善后处理,然后将其 PCB 清零,并将 PCB 空间返还系统。

2.1.4 进程控制块(PCB)
  1. 进程控制块的作用

为了描述和控制进程的运行,系统为每个进程定义了一个数据结构——进程控制块
PCB(Process Control Block),它是进程实体的一部分,是操作系统中最重要的记型数据结构。

PCB 中记录了操作系统所需的、用于描述进程的当前情况以及控制进程运行的全部信息。进程控制块的作用是使一个在多道程序环境下不能独立运行的程序(含数据),成为一个能独立运行的基本单位,一个能与其它进程并发执行的进程。或者说,OS 是根据 PCB 来对并发执行的进程进行控制和管理的。

可见,在进程的整个生命期中,系统总是通过 PCB 对进程进行控制的,亦即,系统是根据进程的 PCB 而不是任何别的什么而感知到该进程的存在的。所以说,PCB 是进程存在的惟一标志。

当系统创建一个新进程时,就为它建立了一个 PCB;进程结束时又回收其 PCB,进程于是也随之消亡。PCB 可以被操作系统中的多个模块读或修改,如被调度程序、资源分配程序、中断处理程序以及监督和分析程序等读或修改。因为 PCB 经常被系统访问,尤其是被运行频率很高的进程及分派程序访问,故 PCB 应常驻内存。系统将所有的 PCB 组织成若干个链表(或队列),存放在操作系统中专门开辟的 PCB 区内。

  1. 进程控制块中的信息

(1) 进程标识符:

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

内部标识符。在所有的操作系统中,都为每一个进程赋予了一个惟一的数字标识符,它通常是一个进程的序号。设置内部标识符主要是为了方便系统使用。

外部标识符。它由创建者提供,通常是由字母、数字组成,往往是由用户(进程)在访问该进程时使用。为了描述进程的家族关系,还应设置父进程标识及子进程标识。此外,还可设置用户标识,以指示拥有该进程的用户。

(2) 处理机状态:

处理机状态信息主要是由处理机的各种寄存器中的内容组成的。处理机在运行时,许多信息都放在寄存器中。当处理机被中断时,所有这些信息都必须保存在 PCB 中,以便在该进程重新执行时,能从断点继续执行。

(3) 进程调度信息:

在 PCB 中还存放一些与进程调度和进程对换有关的信息,包括:

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

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

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

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

(4) 进程控制信息:

进程控制信息包括:① 程序和数据的地址,指进程的程序和数据所在的内存或外存地
(首)址,以便再调度到该进程执行时,能从 PCB 中找到其程序和数据;

② 进程同步和通信机制,指实现进程同步和进程通信时必需的机制,如消息队列指针、信号量等,它们可能全部或部分地放在 PCB 中;

③ 资源清单,即一张列出了除 CPU 以外的、进程所需的全部资源及已经分配到该进程的资源的清单;

④ 链接指针,它给出了本进程(PCB)所在队列中的下一个进程的 PCB 的首地址。

2.2 进程控制

进程控制一般是由 OS 的内核中的原语来实现的。

原语(Primitive)是由若干条指令组成的,用于完成一定功能的一个过程。它与一般过程的区别在于:它们是“原子操作(Action Operation)”。所谓原子操作,是指一个操作中所有动作要么全做,要么全不做。换言之,它是一个不可分割的基本单位,因此,在执行过程中不允许被中断。原子操作在管态下执行,常驻内存。

原语的作用是为了实现进程的通信和控制,系统对进程的控制如不使用原语,就会造成其状态的不确定性,从而达不到进程控制的目的。

管态又叫特权态,系统态或核心态。CPU在管态下可以执行指令系统的全集。通常,操作系统在管态下运行。

目态又叫常态或用户态。机器处于目态时,程序只能执行非特权指令。用户程序只能在目态下运行,如果用户程序在目态下执行特权指令,硬件将发生中断,由操作系统获得控制,特权指令执行被禁止,这样可以防止用户程序有意或无意的破坏系统。

从目态转换为管态的唯一途径是中断。

从管态到目态可以通过修改程序状态字来实现,这将伴随这由操作系统程序到用户程序的转换。

2.2.1 进程的创建
  1. 进程图

进程图是用于描述一个进程的家族关系的有向树,如图 2-11 所示。图中的结点(圆圈)代表进程。在进程 D 创建了进程 I 之后,称 D 是 I 的父进程(Parent Process),I 是 D 的子进程(Progeny Process)。这里可用一条由父进程指向子进程的有向边来描述它们之间的父子关系。创建父进程的进程称为祖先进程,这样便形成了一棵进程树,把树的根结点作为进程家族的祖先(Ancestor)。

了解进程间的这种关系是十分重要的。因为子进程可以继承父进程所拥有的资源,例如,继承父进程打开的文件,继承父进程所分配到的缓冲区等。当子进程被撤消时,应将其从父进程那里获得的资源归还给父进程。此外,在撤消父进程时,也必须同时撤消其所有的子进程。为了标识进程之间的家族关系,在 PCB 中都设置了家族关系表项,以标明自己的父进程及所有的子进程。

  1. 引起创建进程的事件

在多道程序环境中,只有(作为)进程(时)才能在系统中运行。因此,为使程序能运行,就必须为它创建进程。导致一个进程去创建另一个进程的典型事件,可有以下四类:

(1) 用户登录。在分时系统中,用户在终端键入登录命令后,如果是合法用户,系统将为该终端建立一个进程,并把它插入就绪队列中。

(2) 作业调度。在批处理系统中,当作业调度程序按一定的算法调度到某作业时,便将作业装入内存,为它分配必要的资源,并立即为它创建进程,再插入就绪队列中。

(3) 提供服务。当运行中的用户程序提出某种请求后,系统将专门创建一个进程来提供用户所需要的服务,例如,用户程序要求进行文件打印,操作系统将为它创建一个打印进程,这样,不仅可使打印进程与该用户进程并发执行,而且还便于计算出为完成打印任务所花费的时间。

(4) 应用请求。在上述三种情况下,都是由系统内核为它创建一个新进程;而第 4 类事件则是基于应用进程的需求,由它自己创建一个新进程,以便使新进程以并发运行方式完成特定任务。例如,某应用程序需要不断地从键盘终端输入数据,继而又要对输入数据进行相应的处理,然后,再将处理结果以表格形式在屏幕上显示。该应用进程为使这几个操作能并发执行,以加速任务的完成,可以分别建立键盘输入进程、表格输出进程。

  1. 进程的创建

一旦操作系统发现了要求创建新进程的事件后,便调用进程创建原语 Creat() 按下述步骤创建一个新进程。

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

(2) 为新进程分配资源。为新进程的程序和数据以及用户栈分配必要的内存空间。

(3) 初始化进程控制块。PCB 的初始化包括:

① 初始化标识信息,将系统分配的标识符和父进程标识符填入新 PCB 中;

② 初始化处理机状态信息,使程序计数器指向程序的入口地址,使栈指针指向栈顶;

③ 初始化处理机控制信息,将进程的状态设置为就绪状态或静止就绪状态,对于优先级,通常是将它设置为最低优先级,除非用户以显式方式提出高优先级要求。

(4) 将新进程插入就绪队列,如果进程就绪队列能够接纳新进程,便将新进程插入就绪队列。

2.2.2 进程的终止
  1. 进程的终止过程

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

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

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

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

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

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

2.2.3 进程的阻塞与唤醒
  1. 进程阻塞过程

正在执行的进程,当发现上述某事件时,由于无法继续执行,于是进程便通过调用阻塞原语 block 把自己阻塞。可见,进程的阻塞是进程自身的一种主动行为。进入 block过程后,由于此时该进程还处于执行状态,所以应先立即停止执行,把进程控制块中的现行状态由“执行”改为“阻塞”,并将 PCB 插入阻塞队列。如果系统中设置了因不同事件而阻塞的多个阻塞队列,则应将本进程插入到具有相同事件的阻塞(等待)队列。最后,转调度程序进行重新调度,将处理机分配给另一就绪进程并进行切换,亦即,保留被阻塞进程的处理机状态(在 PCB 中),再按新进程的 PCB 中的处理机状态设置 CPU 的环境。

  1. 进程唤醒状态

当被阻塞进程所期待的事件出现时,如 I/O 完成或其所期待的数据已经到达,则由有关进程(比如用完并释放了该 I/O 设备的进程)调用唤醒原语 wakeup( ),将等待该事件的进程唤醒。唤醒原语执行的过程是:首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB 中的现行状态由阻塞改为就绪,然后再将该 PCB 插入到就绪队列中。

应当指出,block 原语和 wakeup 原语是一对作用刚好相反的原语。因此,如果在某进程中调用了阻塞原语,则必须在与之相合作的另一进程中或其他相关的进程中安排唤醒原语,以能唤醒阻塞进程;否则,被阻塞进程将会因不能被唤醒而长久地处于阻塞状态,从
而再无机会继续运行。

2.3 进程同步

在 OS 中引入进程后,虽然提高了资源的利用率和系统的吞吐量,但由于进程的异步性,也会给系统造成混乱,尤其是在他们争用临界资源时。

进程同步的主要任务是对多个相关进程在执行次序上进行协调,以使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。

2.3.1 进程同步的基本概念
  1. 两种形式的制约关系:在多道程序环境下,当程序并发执行时,由于资源共享和进程合作,使同处于一个系统中的诸进程之间可能存在着以下两种形式的制约关系。

(1) 间接相互制约关系。

(2) 直接相互制约关系。

  1. 临界资源

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

  1. 临界区

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

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

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

(1) 空闲让进。当无进程处于临界区时,表明临界资源处于空闲状态,应允许一个请求进入临界区的进程立即进入自己的临界区,以有效地利用临界资源。

(2) 忙则等待。当已有进程进入临界区时,表明临界资源正在被访问,因而其它试图进入临界区的进程必须等待,以保证对临界资源的互斥访问。

(3) 有限等待。对要求访问临界资源的进程,应保证在有限时间内能进入自己的临界区,以免陷入“死等”状态。

(4) 让权等待。当进程不能进入自己的临界区时,应立即释放处理机,以免进程陷入“忙等”状态。

2.3.2 信号量机制

信号量机构是一种功能较强的机制,可用来解决互斥与同步的问题,它只能被两个标准的原语wait(S)和signal(S)来访问,也可以记为“P操作”和“V操作”。

2.3.3 信号量的应用
  1. 利用信号量实现进程互斥。

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

2.3.4 管程机制

虽然信号量机制是一种既方便、又有效的进程同步机制,但每个要访问临界资源的进程都必须自备同步操作 wait(S)和 signal(S)。这就使大量的同步操作分散在各个进程中。这不仅给系统的管理带来了麻烦,而且还会因同步操作的使用不当而导致系统死锁。这样,在解决上述问题的过程中,便产生了一种新的进程同步工具——管程(Monitors)。

  1. 管程的定义

代表共享资源的数据结构,以及由对该共享数据结构实施操作的一组过程所组成的资源管理程序,共同构成了一个操作系统的资源管理模块,我们称之为管程。管程被请求和释放
资源的进程所调用。

2.4 进程通信(very important)

进程通信,是指进程之间的信息交换,其所交换的信息量少者是一个状态或数值,多者则是成千上万个字节。进程之间的互斥和同步,由于其所交换的信息量少而被归结为低级通信。在进程互斥中,进程通过只修改信号量来向其他进程表明临界资源是否可用。

应当指出,信号量机制作为同步工具是卓有成效的,但作为通信工具,则不够理想,主要表现在下述两方面:

(1) 效率低,生产者每次只能向缓冲池投放一个产品(消息),消费者每次只能从缓冲区中取得一个消息;

(2) 通信对用户不透明。

2.4.1 进程通信的类型

目前,高级通信机制可归结为三大类:共享存储器系统、消息传递系统以及管道通信系统。

  1. 共享存储器系统

(1) 基于共享数据结构的通信方式。这种通信方式是低效的,只适于传递相对少量的数据。

(2) 基于共享存储区的通信方式。为了传输大量数据,在存储器中划出了一块共享存储区,诸进程可通过对共享存储区中数据的读或写来实现通信。

  1. 消息传递系统

消息传递系统(Message passing system)是当前应用最为广泛的一种进程间的通信机制。在该机制中,进程间的数据交换是以格式化的消息(message)为单位的;在计算机网络中,又把 message 称为报文。程序员直接利用操作系统提供的一组通信命令(原语),不仅能实现大量数据的传递,而且还隐藏了通信的实现细节,使通信过程对用户是透明的,从而大大减化了通信程序编制的复杂性,因而获得了广泛的应用。

特别值得一提的是,在当今最为流行的微内核操作系统中,微内核与服务器之间的通信,无一例外地都采用了消息传递机制。又由于它能很好地支持多处理机系统、分布式系统和计算机网络,因此它也成为这些领域最主要的通信工具。消息传递系统的通信方式属于高级通信方式。又因其实现方式的不同而进一步分成直接通信方式和间接通信方式两种。

  1. 管道通信

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

为了协调双方的通信,管道机制必须提供以下三方面的协调能力:

(1) 互斥,即当一个进程正在对 pipe 执行读/写操作时,其它(另一)进程必须等待。

(2) 同步,指当写(输入)进程把一定数量(如 4 KB)的数据写入 pipe,便去睡眠等待,直到读(输出)进程取走数据后,再把它唤醒。当读进程读一空 pipe 时,也应睡眠等待,直至写进程将数据写入管道后,才将之唤醒。

(3) 确定对方是否存在,只有确定了对方已存在时,才能进行通信。

2.5 线程

2.5.1 线程的基本概念
  1. 线程的引入

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

  1. 线程与进程的比较

线程具有许多传统进程所具有的特征,所以又称为轻型进程(Light-Weight Process)或进程元,相应地把传统进程称为重型进程(Heavy-Weight Process),传统进程相当于只有一个线程的任务。在引入了线程的操作系统中,通常一个进程都拥有若干个线程,至少也有一个线程。下面我们从调度性、并发性、系统开销和拥有资源等方面对线程和进程进行比较。

(1) 调度

在传统的操作系统中,作为拥有资源的基本单位和独立调度、分派的基本单位都是进程。而在引入线程的操作系统中,则把线程作为调度和分派的基本单位,而进程作为资源拥有的基本单位,把传统进程的两个属性分开,使线程基本上不拥有资源,这样线程便能轻装前进,从而可显著地提高系统的并发程度。在同一进程中,线程的切换不会引起进程的切换,但从一个进程中的线程切换到另一个进程中的线程时,将会引起进程的切换。

(2) 并发性

在引入线程的操作系统中,不仅进程之间可以并发执行,而且在一个进程中的多个线程之间亦可并发执行,使得操作系统具有更好的并发性,从而能更加有效地提高系统资源的利用率和系统的吞吐量。

(3) 拥有资源

不论是传统的操作系统,还是引入了线程的操作系统,进程都可以拥有资源,是系统中拥有资源的一个基本单位。一般而言,线程自己不拥有系统资源(也有一点必不可少的资源),但它可以访问其隶属进程的资源,即一个进程的代码段、数据段及所拥有的系统资源,如已打开的文件、I/O 设备等,可以供该进程中的所有线程所共享。

(4) 系统开销

在创建或撤消进程时,系统都要为之创建和回收进程控制块,分配或回收资源,如内存空间和 I/O 设备等,操作系统所付出的开销明显大于线程创建或撤消时的开销。

  1. 线程的属性

(1) 轻型实体。线程中的实体基本上不拥有系统资源,只是有一点必不可少的、 能保证其独立运行的资源,比如,在每个线程中都应具有一个用于控制线程运行的线程控制块TCB,用于指示被执行指令序列的程序计数器,保留局部变量、少数状态参数和返回地址等的一组寄存器和堆栈。

(2) 独立调度和分派的基本单位。在多线程 OS 中,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很“轻”,故线程的切换非常迅速且开销小。

(3) 可并发执行。在一个进程中的多个线程之间可以并发执行,甚至允许在一个进程中的所有线程都能并发执行;同样,不同进程中的线程也能并发执行。

(4) 共享进程资源。在同一进程中的各个线程都可以共享该进程所拥有的资源,这首先表现在所有线程都具有相同的地址空间(进程的地址空间)。这意味着线程可以访问该地址空间中的每一个虚地址;此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等。

2.6 线程间的同步和通信

  1. 互斥锁

互斥锁是一种比较简单的、用于实现线程间对资源互斥访问的机制。由于操作互斥锁的时间和空间开销都较低,因而较适合于高频度使用的关键共享数据和程序段。

  1. 条件变量

在许多情况下,只利用 mutex 来实现互斥访问可能会引起死锁,每一个条件变量通常都与一个互斥锁一起使用,亦即,在创建一个互斥锁时便联系着一个条件变量。单纯的互斥锁用于短期锁定,主要是用来保证对临界区的互斥进入。而条件变量则用于线程的长期等待,直至所等待的资源成为可用的资源。

  1. 信号量机制

前面所介绍的用于实现进程同步的最常用工具——信号量机制,也可用于多线程 OS中,实现诸线程或进程之间的同步。为了提高效率,可为线程和进程分别设置相应的信号量。

第三章 处理机调度与死锁

3.1 调度算法

3.1.1 先来先服务和短作业(进程)优先调度算法
  1. 先来先服务调度算法

先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。

在进程调度中采用 FCFS 算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。FCFS 算法比较有利于长作业(进程),而不利于短作业(进程)。

  1. 短作业(进程)优先调度算法

短作业(进程)优先调度算法 SJ(P)F,是指对短作业或短进程优先调度的算法。它们可以分别用于作业调度和进程调度。短作业优先(SJF)的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。

SJ(P)F 调度算法也存在不容忽视的缺点:

(1) 该算法对长作业不利,如作业 C 的周转时间由 10 增至 16,其带权周转时间由 2 增至 3.1。更严重的是,如果有一长作业(进程)进入系统的后备队列(就绪队列),由于调度程序总是优先调度那些(即使是后进来的)短作业(进程),将导致长作业(进程)长期不被调度。

(2) 该算法完全未考虑作业的紧迫程度,因而不能保证紧迫性作业(进程)会被及时处理。

(3) 由于作业(进程)的长短只是根据用户所提供的估计执行时间而定的,而用户又可能会有意或无意地缩短其作业的估计运行时间,致使该算法不一定能真正做到短作业优先调度。

3.1.2 高优先权优先调度算法
  1. 优先权调度算法的类型

为了照顾紧迫型作业,使之在进入系统后便获得优先处理,引入了最高优先权优先(FPF)调度算法。此算法常被用于批处理系统中,作为作业调度算法,也作为多种操作系统中的进程调度算法,还可用于实时系统中。当把该算法用于作业调度时,系统将从后备队列中选择若干个优先权最高的作业装入内存。当用于进程调度时,该算法是把处理机分配给就绪队列中优先权最高的进程,这时,又可进一步把该算法分成如下两种。

(1) 非抢占式优先权算法

在这种方式下,系统一旦把处理机分配给就绪队列中优先权最高的进程后,该进程便一直执行下去,直至完成;或因发生某事件使该进程放弃处理机时,系统方可再将处理机重新分配给另一优先权最高的进程。这种调度算法主要用于批处理系统中;也可用于某些对实时性要求不严的实时系统中。

(2) 抢占式优先权调度算法

在这种方式下,系统同样是把处理机分配给优先权最高的进程,使之执行。但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。

显然,这种抢占式的优先权调度算法能更好地满足紧迫作业的要求,故而常用于要求比较严格的实时系统中,以及对性能要求较高的批处理和分时系统中。

  1. 优先权的类型

(1) 静态优先权

静态优先权是在创建进程时确定的,且在进程的整个运行期间保持不变。

确定进程优先权的依据有如下三个方面:

① 进程类型。通常,系统进程(如接收进程、对换进程、磁盘 I/O 进程)的优先权高于一般用户进程的优先权。

② 进程对资源的需求。如进程的估计执行时间及内存需要量的多少,对这些要求少的进程应赋予较高的优先权。

③ 用户要求。这是由用户进程的紧迫程度及用户所付费用的多少来确定优先权的。

静态优先权法简单易行,系统开销小,但不够精确,很可能出现优先权低的作业(进程)长期没有被调度的情况。因此,仅在要求不高的系统中才使用静态优先权。

(2) 动态优先权

动态优先权是指在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能。

  1. 高响应比优先调度算法

如果我们能为每个作业引入前面所述的动态优先权,并使作业的优先级随着等待时间的增加而以速率 a 提高,则长作业在等待一定的时间后,必然有机会分配到处理机。该优先权的变化规律可描述为:

优先权 = (等待时间 + 要求服务时间) / 要求服务时间

由于等待时间与服务时间之和就是系统对该作业的响应时间,故该优先权又相当于响应比 RP。据此,又可表示为:

RP = (等待时间 + 要求服务时间) / 要求服务时间 = 响应时间 / 要求服务时间

由上式可以看出:

(1) 如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业。

(2) 当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务。

(3) 对于长作业,作业的优先级可以随等待时间的增加而提高,当其等待时间足够长时,其优先级便可升到很高,从而也可获得处理机。

简言之,该算法既照顾了短作业,又考虑了作业到达的先后次序,不会使长作业长期得不到服务。因此,该算法实现了一种较好的折衷。当然,在利用该算法时,每要进行调度之前,都须先做响应比的计算,这会增加系统开销。

3.1.3 基于时间片的轮转调度算法

在早期,分时系统中采用的是简单的时间片轮转法;进入 20 世纪 90年代后,广泛采用多级反馈队列调度算法

  1. 时间片轮转法

在早期的时间片轮转法中,系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把 CPU 分配给队首进程,并令其执行一个时间片。时间片的大小从几 ms 到几百 ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程在一给定的时间内均能获得一时间片的处理机执行时间。换言之,系统能在给定的时间内响应所有用户的请求。

  1. 多级反馈队列调度算法

前面介绍的各种用作进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程,而且如果并未指明进程的长度,则短进程优先和基于进程长度的抢占式调度算法都将无法使用。而多级反馈队列调度算法则不必事先知道各种进程所需的执行时间,而且还可以满足各种类型进程的需要,因而它是目前被公认的一种较好的进程调度算法。在采用多级反馈队列调度算法的系统中,调度算法的实施过程如下所述。

(1) 应设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍,……,第 i+1 个队列的时间片要比第 i 个队列的时间片长一倍。图 3-7 是多级反馈队列算法的示意。

(2) 当一个新进程进入内存后,首先将它放入第一队列的末尾,按 FCFS 原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按 FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第 n 队列后,在第 n 队列中便采取按时间片轮转的方式运行。

(3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第 1~(i-1)队列均空时,才会调度第 i 队列中的进程运行。如果处理机正在第 i 队列中为某进程服务时,又有新进程进入优先权较高的队列(第 1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第 i 队列的末尾,把处理机分配给新到的高优先权进程。

  1. 多级反馈队列调度算法的性能

多级反馈队列调度算法具有较好的性能,能很好地满足各种类型用户的需要。

(1) 终端型作业用户。由于终端型作业用户所提交的作业大多属于交互型作业,作业通常较小,系统只要能使这些作业(进程)在第一队列所规定的时间片内完成,便可使终端型作业用户都感到满意。

(2) 短批处理作业用户。对于很短的批处理型作业,开始时像终端型作业一样,如果仅在第一队列中执行一个时间片即可完成,便可获得与终端型作业一样的响应时间。对于稍长的作业,通常也只需在第二队列和第三队列各执行一个时间片即可完成,其周转时间仍然较短。

(3) 长批处理作业用户。对于长作业,它将依次在第 1,2,…,n 个队列中运行,然后再按轮转方式运行,用户不必担心其作业长期得不到处理。

3.2 实时调度

由于在实时系统中都存在着若干个实时进程或任务,它们用来反应或控制某个(些)外部事件,往往带有某种程度的紧迫性,因而对实时系统中的调度提出了某些特殊要求。前面所介绍的多种调度算法并不能很好地满足实时系统对调度的要求,为此,需要引入一种新的调度,即实时调度。

3.2.1 实现实时调度的基本条件

1.提供必要的信息

(1) 就绪时间。这是该任务成为就绪状态的起始时间,在周期任务的情况下,它就是事先预知的一串时间序列;而在非周期任务的情况下,它也可能是预知的。

(2) 开始截止时间和完成截止时间。对于典型的实时应用,只须知道开始截止时间,或者知道完成截止时间。

(3) 处理时间。这是指一个任务从开始执行直至完成所需的时间。在某些情况下,该时间也是系统提供的。

(4) 资源要求。这是指任务执行时所需的一组资源。

(5) 优先级。如果某任务的开始截止时间已经错过,就会引起故障,则应为该任务赋予“绝对”优先级;如果开始截止时间的推迟对任务的继续运行无重大影响,则可为该任务赋予“相对”优先级,供调度程序参考。

  1. 处理能力强

在实时系统中,通常都有着多个实时任务。若处理机的处理能力不够强,则有可能因处理机忙不过来而使某些实时任务不能得到及时处理,从而导致发生难以预料的后果。

  1. 采用抢占式调度机制

在含有硬实时任务的实时系统中,广泛采用抢占机制。当一个优先权更高的任务到达时,允许将当前任务暂时挂起,而令高优先权任务立即投入运行,这样便可满足该硬实时任务对截止时间的要求。但这种调度机制比较复杂。

对于一些小型实时系统,如果能预知任务的开始截止时间,则对实时任务的调度可采用非抢占调度机制,以简化调度程序和对任务调度时所花费的系统开销。但在设计这种调度机制时,应使所有的实时任务都比较小,并在执行完关键性程序和临界区后,能及时地将自己阻塞起来,以便释放出处理机,供调度程序去调度那种开始截止时间即将到达的任务。

  1. 具有快速切换机制

为保证要求较高的硬实时任务能及时运行,在实时系统中还应具有快速切换机制,以保证能进行任务的快速切换。该机制应具有如下两方面的能力:

(1) 对外部中断的快速响应能力。

(2) 快速的任务分派能力。

3.2.2 常用的几种实时调度算法

1.最早截止时间优先即 EDF(Earliest Deadline First)算法

该算法是根据任务的开始截止时间来确定任务的优先级。截止时间愈早,其优先级愈高。该算法要求在系统中保持一个实时任务就绪队列,该队列按各任务截止时间的早晚排序;当然,具有最早截止时间的任务排在队列的最前面。调度程序在选择任务时,总是选择就绪队列中的第一个任务,为之分配处理机,使之投入运行。最早截止时间优先算法既可用于抢占式调度,也可用于非抢占式调度方式中。

2.最低松弛度优先即 LLF(Least Laxity First)算法

该算法是根据任务紧急(或松弛)的程度,来确定任务的优先级。任务的紧急程度愈高,为该任务所赋予的优先级就愈高,以使之优先执行。

3.3 产生死锁的原因和必要条件

3.3.1 产生死锁的原因

产生死锁的原因可归结为如下两点:

(1) 竞争资源。当系统中供多个进程共享的资源如打印机、公用队列等,其数目不足以满足诸进程的需要时,会引起诸进程对资源的竞争而产生死锁。

(2) 进程间推进顺序非法。进程在运行过程中,请求和释放资源的顺序不当,也同样会导致产生进程死锁。

3.3.2 产生死锁的必要条件

死锁的发生必须具备下列四个必要条件。

(1) 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求该资源,则请求者只能等待,直至占有该资源的进程用毕释放。

(2) 请求和保持条件:指进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

(3) 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

(4) 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,…,Pn}中的 P0正在等待一个 P1占用的资源; P1正在等待 P2占用的资源,……,Pn正在等待已被 P0占用的资源。

3.3.3 处理死锁的基本方法

预防,避免,检测,解除

3.4 预防死锁的方法

3.4.1 预防死锁

预防死锁的方法是使四个必要条件中的第 2、3、4 个条件之一不能成立,来避免发生死锁。至于必要条件 1,因为它是由设备的固有特性所决定的,不仅不能改变,还应加以保证。

  1. 摒弃“请求和保持”条件

在采用这种方法时,系统规定所有进程在开始运行之前,都必须一次性地申请其在整个运行过程所需的全部资源。此时,若系统有足够的资源分配给某进程,便可把其需要的所有资源分配给该进程,这样,该进程在整个运行期间便不会再提出资源要求,从而摒弃了请求条件。

这种预防死锁的方法其优点是简单、易于实现且很安全。但其缺点却也极其明显:首
先表现为资源被严重浪费,其次是使进程延迟运行,仅当进程在获得了其所需的全部资源后,才能开始运行,但可能因有些资源已长期被其它进程占用而致使等待该资源的进程迟迟不能运行。

  1. 摒弃“不剥夺”条件

在采用这种方法时系统规定,进程是逐个地提出对资源的要求的。当一个已经保持了某些资源的进程,再提出新的资源请求而不能立即得到满足时,必须释放它已经保持了的所有资源,待以后需要时再重新申请。这意味着某一进程已经占有的资源,在运行过程中会被暂时地释放掉,也可认为是被剥夺了,从而摒弃了“不剥夺”条件。

这种预防死锁的方法实现起来比较复杂且要付出很大的代价。此外,这种策略还可能因
为反复地申请和释放资源,致使进程的执行被无限地推迟,这不仅延长了进程的周转时间,
而且也增加了系统开销,降低了系统吞吐量。

  1. 摒弃“环路等待”条件

这种方法中规定,系统将所有资源按类型进行线性排队,并赋予不同的序号。例如,令输入机的序号为 1,打印机的序号为 2,磁带机为 3,磁盘为 4。所有进程对资源的请求必须严格按照资源序号递增的次序提出,这样,在所形成的资源分配图中,不可能再出现环路,因而摒弃了“环路等待”条件。

首先是为系统中各类资源所分配(确定)的序号必须相对稳定,这就限制了新类型设备的增加。为方便用户,系统对用户在编程时所施加的限制条件应尽量少。然而这种按规定次序申请的方法,必然会限制用户简单、自主地编程。

3.4.2 系统安全状态

在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可避免发生死锁。

  1. 安全状态

所谓安全状态,是指系统能按某种进程顺序(P1,P2,…,Pn)(称〈P1,P2,…,Pn〉序列为安全序列),来为每个进程 Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺利地完成。如果系统无法找到这样一个安全序列,则称系统处于不安全状态。

虽然并非所有的不安全状态都必然会转为死锁状态,但当系统进入不安全状态后,便有可能进而进入死锁状态;反之,只要系统处于安全状态,系统便可避免进入死锁状态。因此,避免死锁的实质在于:系统在进行资源分配时,如何使系统不进入不安全状态。

3.5 死锁的检测与解除

3.5.1 死锁的解除

当发现有进程死锁时,便应立即把它们从死锁状态中解脱出来。常采用解除死锁的两种方法是:

(1) 剥夺资源。从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态。

(2) 撤消进程。最简单的撤消进程的方法是使全部死锁进程都夭折掉;稍微温和一点的方法是按照某种顺序逐个地撤消进程,直至有足够的资源可用,使死锁状态消除为止。

第四章 存储器管理

4.1 存储器的层次结构

4.1.1 多级存储器结构

对于通用计算机而言,存储层次至少应具有三级:最高层为 CPU 寄存器,中间为主存,最底层是辅存。在较高档的计算机中,还可以根据具体的功能分工细划为寄存器、高速缓存、主存储器、磁盘缓存、固定磁盘、可移动存储介质等 6 层。如图 4-1 所示,在存储层次中越往上,存储介质的访问速度越快,价格也越高,相对存储容量也越小。其中,寄存器、高速缓存、主存储器和磁盘缓存均属于操作系统存储管理的管辖范畴,掉电后它们存储的信息不再存在。固定磁盘和可移动存储介质属于设备管理的管辖范畴,它们存储的信息将被长期保存。

4.1.2 主存储器与寄存器
  1. 主存储器

主存储器(简称内存或主存)是计算机系统中一个主要部件,用于保存进程运行时的程序和数据,也称可执行存储器,CPU的控制部件只能从主存储器中取得指令和数据,数据能够从主存储器读取并将它们装入到寄存器中,或者从寄存器存入到主存储器。CPU 与外围设备交换的信息一般也依托于主存储器地址空间。由于主存储器的访问速度远低于 CPU 执行指令的速度,为缓和这一矛盾,在计算机系统中引入了寄存器和高速缓存。

  1. 寄存器

寄存器访问速度最快,完全能与 CPU 协调工作,但价格却十分昂贵,因此容量不可能做得很大。寄存器的长度一般以字(word)为单位。寄存器用于加速存储器的访问速度,如用寄存器存放操作数,或用作地址寄存器加快地址转换速度等。

4.1.3 高速缓存和磁盘缓存
  1. 高速缓存

高速缓存是现代计算机结构中的一个重要部件,其容量大于或远大于寄存器,而比内存约小两到三个数量级左右,从几十 KB 到几 MB,访问速度快于主存储器。

根据程序执行的局部性原理(即程序在执行时将呈现出局部性规律,在一较短的时间内,程序的执行仅局限于某个部分),将主存中一些经常访问的信息存放在高速缓存中,减少访问主存储器的次数,可大幅度提高程序执行速度。通常,进程的程序和数据是存放在主存储器中,每当使用时,被临时复制到一个速度较快的高速缓存中。当 CPU 访问一组特定信息时,首先检查它是否在高速缓存中,如果已存在,可直接从中取出使用,以避免访问主存,否则,再从主存中读出信息。

  1. 磁盘缓存

由于目前磁盘的 I/O 速度远低于对主存的访问速度,因此将频繁使用的一部分磁盘数据和信息,暂时存放在磁盘缓存中,可减少访问磁盘的次数。磁盘缓存本身并不是一种实际存在的存储介质,它依托于固定磁盘,提供对主存储器存储空间的扩充,即利用主存中的存储空间,来暂存从磁盘中读出(或写入)的信息。主存也可以看做是辅存的高速缓存,因为,辅存中的数据必须复制到主存方能使用;反之,数据也必须先存在主存中,才能输出到辅存。

4.2 程序的装入和链接

在多道程序环境下,要使程序运行,必须先为之创建进程。而创建进程的第一件事,便是将程序和数据装入内存。如何将一个用户源程序变为一个可在内存中执行的程序,通常都要经过以下几个步骤:首先是要编译,由编译程序(Compiler)将用户源代码编译成若干个目标模块(Object Module);其次是链接,由链接程序(Linker)将编译后形成的一组目标模块,以及它们所需要的库函数链接在一起,形成一个完整的装入模块(Load Module);最后是装入,由装入程序(Loader)将装入模块装入内存。

4.2.1 程序的装入
  1. 绝对装入方式

在编译时,如果知道程序将驻留在内存的什么位置,那么,编译程序将产生绝对地址的目标代码。

绝对装入程序按照装入模块中的地址,将程序和数据装入内存。装入模块被装入内存后,由于程序中的逻辑地址与实际内存地址完全相同,故不须对程序和数据的地址进行修改。

  1. 可重定位装入方式

在多道程序环境下,所得到的目标模块的起始地址通常是从 0 开始的,程序中的其它地址也都是相对于起始地址计算的。此时应采用可重定位装入方式,根据内存的当前情况,将装入模块装入到内存的适当位置。

通常是把在装入时对目标程序中指令和数据的修改过程称为重定位。又因为地址变换通常是在装入时一次完成的,以后不再改变,故称为静态重定位。

  1. 动态运行时装入方式

动态运行时的装入程序在把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址都仍是相对地址。为使地址转换不影响指令的执行速度,这种方式需要一个重定位寄存器的支持。

4.2.2 程序的链接

源程序经过编译后,可得到一组目标模块,再利用链接程序将这组目标模块链接,形
成装入模块。根据链接时间的不同,可把链接分成如下三种:

(1) 静态链接。在程序运行之前,先将各目标模块及它们所需的库函数,链接成一个完整的装配模块,以后不再拆开。我们把这种事先进行链接的方式称为静态链接方式。

(2) 装入时动态链接。这是指将用户源程序编译后所得到的一组目标模块,在装入内存时,采用边装入边链接的链接方式。

(3) 运行时动态链接。这是指对某些目标模块的链接,是在程序执行中需要该(目标)模块时,才对它进行的链接。

4.3 连续分配方式

连续分配方式,是指为一个用户程序分配一个连续的内存空间。

4.3.1 单一连续分配

这是最简单的一种存储管理方式,但只能用于单用户、单任务的操作系统中。采用这种存储管理方式时,可把内存分为系统区和用户区两部分,系统区仅提供给 OS 使用,通常是放在内存的低址部分;用户区是指除系统区以外的全部内存空间,提供给用户使用。

4.3.2 固定分区分配

固定分区式分配是最简单的一种可运行多道程序的存储管理方式。这是将内存用户空间划分为若干个固定大小的区域,在每个分区中只装入一道作业,这样,把用户空间划分为几个分区,便允许有几道作业并发运行。当有一空闲分区时,便可以再从外存的后备作业队列中选择一个适当大小的作业装入该分区,当该作业结束时,又可再从后备作业队列中找出另一作业调入该分区。

  1. 划分分区的方法

(1) 分区大小相等,即使所有的内存分区大小相等。其缺点是缺乏灵活性,即当程序太小时,会造成内存空间的浪费;当程序太大时,一个分区又不足以装入该程序,致使该程序无法运行。

(2) 分区大小不等。为了克服分区大小相等而缺乏灵活性的这个缺点,可把内存区划分成含有多个较小的分区、适量的中等分区及少量的大分区。这样,便可根据程序的大小为之分配适当的分区。

  1. 内存分配

为了便于内存分配,通常将分区按大小进行排队,并为之建立一张分区使用表,其中各表项包括每个分区的起始地址、大小及状态(是否已分配),见图 4-5(a)所示。当有一用户程序要装入时,由内存分配程序检索该表,从中找出一个能满足要求的、尚未分配的分区,将之分配给该程序,然后将该表项中的状态置为“已分配”;若未找到大小足够的分区,则拒绝为该用户程序分配内存。存储空间分配情况如图 4-5(b)所示。

4.3.3 动态分区分配
  1. 分区分配算法

(1) 首次适应算法(first fit)

我们以空闲分区链为例来说明采用 FF 算法时的分配情况。FF 算法要求空闲分区链以地址递增的次序链接。在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止;然后再按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲链中。若从链首直至链尾都不能找到一个能满足要求的分区,则此次内存分配失败,返回。该算法倾向于优先利用内存中低址部分的空闲分区,从而保留了高址部分的大空闲区。这给为以后到达的大作业分配大的内存空间创造了条件。其缺点是低址部分不断被划分,会留下许多难以利用的、很小的空闲分区,而每次查找又都是从低址部分开始,这无疑会增加查找可用空闲分区时的开销。

(2) 循环首次适应算法(next fit)

该算法是由首次适应算法演变而成的。在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块与请求大小相等的内存空间分配给作业。为实现该算法,应置一起始查寻指针,用于指示下一次起始查寻的空闲分区,并采用循环查找方式,即如果最后一个(链尾)空闲分区的大小仍不能满足要求,则应返回到第一个空闲分区,比较其大小是否满足要求。找到后,应调整起始查寻指针。该算法能使内存中的空闲分区分布得更均匀,从而减少了查找空闲分区时的开销,但这样会缺乏大的空闲分区。

(3) 最佳适应算法(best fit)

所谓“最佳”是指每次为作业分配内存时,总是把能满足要求、又是最小的空闲分区分配给作业,避免“大材小用”。为了加速寻找,该算法要求将所有的空闲分区按其容量以从小到大的顺序形成一空闲分区链。这样,第一次找到的能满足要求的空闲区,必然是最佳的。孤立地看,最佳适应算法似乎是最佳的,然而在宏观上却不一定。因为每次分配后所切割下来的剩余部分总是最小的,这样,在存储器中会留下许多难以利用的小空闲区。

(4) 最坏适应算法(worst fit)

最坏适应分配算法要扫描整个空闲分区表或链表,总是挑选一个最大的空闲区分割给作业使用,其优点是可使剩下的空闲区不至于太小,产生碎片的几率最小,对中、小作业有利,同时最坏适应分配算法查找效率很高。该算法要求将所有的空闲分区按其容量以从大到小的顺序形成一空闲分区链,查找时只要看第一个分区能否满足作业要求。但是该算法的缺点也是明显的,它会使存储器中缺乏大的空闲分区。最坏适应算法与前面所述的首次适应算法、循环首次适应算法、最佳适应算法一起,也称为顺序搜索法。

(5) 快速适应算法(quick fit)

该算法又称为分类搜索法,是将空闲分区根据其容量大小进行分类,对于每一类具有相同容量的所有空闲分区,单独设立一个空闲分区链表,这样,系统中存在多个空闲分区链表,同时在内存中设立一张管理索引表,该表的每一个表项对应了一种空闲分区类型,并记录了该类型空闲分区链表表头的指针。空闲分区的分类是根据进程常用的空间大小进行划分,如 2 KB、4 KB、8 KB 等,对于其它大小的分区,如 7 KB 这样的空闲区,既可以放在 8 KB 的链表中,也可以放在一个特殊的空闲区链表中。

该算法的优点是查找效率高,仅需要根据进程的长度,寻找到能容纳它的最小空闲区链表,并取下第一块进行分配即可。另外该算法在进行空闲分区分配时,不会对任何分区产生分割,所以能保留大的分区,满足对大空间的需求,也不会产生内存碎片。该算法的缺点是在分区归还主存时算法复杂,系统开销较大。此外,该算法在分配空闲分区时是以进程为单位,一个分区只属于一个进程,因此在为进程所分配的一个分区中,或多或少地存在一定的浪费。空闲分区划分越细,浪费则越严重,整体上会造成可观的存储空间浪费,这是典型的以空间换时间的作法。

  1. 分区分配操作

(1) 分配内存

系统应利用某种分配算法,从空闲分区链(表)中找到所需大小的分区。

(2) 回收内存

4.3.4 可重定位分区分配
  1. 动态重定位的引入

在连续分配方式中,必须把一个系统或用户程序装入一连续的内存空间。如果在系统中只有若干个小的分区,即使它们容量的总和大于要装入的程序,但由于这些分区不相邻接,也无法把该程序装入内存。

若想把作业装入,可采用的一种方法是:将内存中的所有作业进行移动,使它们全都相邻接,这样,即可把原来分散的多个小分区拼接成一个大分区,这时就可把作业装入该区。这种通过移动内存中作业的位置,以把原来多个分散的小分区拼接成一个大分区的方法,称为“拼接”或“紧凑”,见图 4-9(b)。由于经过紧凑后的某些用户程序在内存中的位置发生了变化,此时若不对程序和数据的地址加以修改(变换),则程序必将无法执行。为此,在每次“紧凑”后,都必须对移动了的程序或数据进行重定位。

  1. 动态重定位的实现

在动态运行时装入的方式中,作业装入内存后的所有地址都仍然是相对地址,将相对地址转换为物理地址的工作,被推迟到程序指令要真正执行时进行。为使地址的转换不会影响到指令的执行速度,必须有硬件地址变换机构的支持,即须在系统中增设一个重定位寄存器,用它来存放程序(数据)在内存中的起始地址。程序在执行时,真正访问的内存地址是相对地址与重定位寄存器中的地址相加而形成的。

  1. 动态重定位分区分配算法

动态重定位分区分配算法与动态分区分配算法基本上相同,差别仅在于:在这种分配算法中,增加了紧凑的功能,通常,在找不到足够大的空闲分区来满足用户需求时进行紧凑。

4.3.5 对换
  1. 对换的引入

所谓“对换”,是指把内存中暂时不能运行的进程或者暂时不用的程序和数据调出到外存上,以便腾出足够的内存空间,再把已具备运行条件的进程或进程所需要的程序和数据调入内存。对换是提高内存利用率的有效措施。

如果对换是以整个进程为单位的,便称之为“整体对换”或“进程对换”。

而如果对换是以“页”或“段”为单位进行的,则分别称之为“页面对换”或“分段对换”,又统称为“部分对换”。

  1. 对换空间的管理

在具有对换功能的 OS 中,通常把外存分为文件区和对换区。前者用于存放文件,后者用于存放从内存换出的进程。

故对文件区管理的主要目标,是提高文件存储空间的利用率。对对换空间管理的主要目标,是提高进程换入和换出的速度。

由于对换分区的分配是采用连续分配方式,因而对换空间的分配与回收,与动态分区方式时的内存分配与回收方法雷同。其分配算法可以是首次适应算法、循环首次适应算法或最佳适应算法。具体的分配操作,也与内存的分配过程相同,这里不再赘述。

  1. 进程的换入与换出

(1) 进程的换出。每当一进程由于创建子进程而需要更多的内存空间,但又无足够的内存空间等情况发生时,系统应将某进程换出。其过程是:系统首先选择处于阻塞状态且优先级最低的进程作为换出进程,然后启动磁盘,将该进程的程序和数据传送到磁盘的对换区上。

(2) 进程的换入。

系统应定时地查看所有进程的状态,从中找出“就绪”状态但已换出的进程,将其中换出时间最久(换出到磁盘上)的进程作为换入进程,将之换入,直至已无可换入的进程或无可换出的进程为止。

4.4 基本分页存储管理方式

4.1.1 页面与页表
  1. 页面

(1) 页面和物理块

分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号,从 0 开始,如第 0 页、第 1 页等。相应地,也把内存空间分成与页面相同大小的若干个存储块,称为(物理)块或页框(frame),也同样为它们加以编号,如 0#块、1#块等等。在为进程分配内存时,以块为单位将进程中的若干个页分别装入到多个可以不相邻接的物理块中。由于进程的最后一页经常装不满一块而形成了不可利用的碎片,称之为“页内碎片”。

(2) 页面大小

在分页系统中的页面其大小应适中。页面若太小,一方面虽然可使内存碎片减小,从而减少了内存碎片的总空间,有利于提高内存利用率,但另一方面也会使每个进程占用较多的页面,从而导致进程的页表过长,占用大量内存;此外,还会降低页面换进换出的效率。然而,如果选择的页面较大,虽然可以减少页表的长度,提高页面换进换出的速度,但却又会使页内碎片增大。因此,页面的大小应选择适中,且页面大小应是 2 的幂,通常为 512 B~8 KB。

  1. 页表

在分页系统中,允许将进程的各个页离散地存储在内存不同的物理块中,但系统应能保证进程的正确运行,即能在内存中找到每个页面所对应的物理块。为此,系统又为每个进程建立了一张页面映像表,简称页表。在进程地址空间内的所有页(0~n),依次在页表中有一页表项,其中记录了相应页在内存中对应的物理块号,见图 4-12 的中间部分。在配置了页表后,进程执行时,通过查找该表,即可找到每页在内存中的物理块号。可见,页表的作用是实现从页号到物理块号的地址映射。

4.5 基本分段存储管理方式

4.5.1 分段系统的基本原理
  1. 分段

在分段存储管理方式中,作业的地址空间被划分为若干个段,每个段定义了一组逻辑
信息。

  1. 段表

在前面所介绍的动态分区分配方式中,系统为整个进程分配一个连续的内存空间。而在分段式存储管理系统中,则是为每个分段分配一个连续的分区,而进程中的各个段可以离散地移入内存中不同的分区中。为使程序能正常运行,亦即,能从物理内存中找出每个逻辑段所对应的位置,应像分页系统那样,在系统中为每个进程建立一张段映射表,简称“段表”。

  1. 分页和分段的主要区别

(1) 页是信息的物理单位,分页是为实现离散分配方式,以消减内存的外零头,提高内存的利用率。或者说,分页仅仅是由于系统管理的需要而不是用户的需要。段则是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了能更好地满足用户的需要。

(2) 页的大小固定且由系统决定,由系统把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而在系统中只能有一种大小的页面;而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时,根据信息的性质来划分。

(3) 分页的作业地址空间是一维的,即单一的线性地址空间,程序员只需利用一个记忆符,即可表示一个地址;而分段的作业地址空间则是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。

4.5.2 段页式存储管理方式

分页系统能有效地提高内存利用率,而分段系统则能很好地满足用户需要。如果能对两种存储管理方式“各取所长”,则可以将两者结合成一种新的存储管理方式系统。这种新系统既具有分段系统的便于实现、分段可共享、易于保护、可动态链接等一系列优点,又能像分页系统那样很好地解决内存的外部碎片问题,以及可为各个分段离散地分配内存等问题。把这种结合起来形成的新系统称为“段页式系统”。

  1. 基本原理
    段页式系统的基本原理,是分段和分页原理的结合,即先将用户程序分成若干个段,
    再把每个段分成若干个页,并为每一个段赋予一个段名。

4.6 虚拟存储器的基本概念

4.6.1 虚拟存储器的引入
  1. 局部性原理

(1) 时间局限性。如果程序中的某条指令一旦执行,则不久以后该指令可能再次执行;如果某数据被访问过,则不久以后该数据可能再次被访问。产生时间局限性的典型原因是由于在程序中存在着大量的循环操作。

(2) 空间局限性。一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内,其典型情况便是程序的顺序执行。

  1. 虚拟存储器的定义

由上所述可以得知,所谓虚拟存储器,是指具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统。

4.6.2 虚拟存储器的实现方法

1.分页请求系统

2.请求分段系统

4.6.3 虚拟存储器的特征
  1. 多次性

多次性是指一个作业被分成多次调入内存运行,亦即在作业运行时没有必要将其全部装入,只需将当前要运行的那部分程序和数据装入内存即可。

  1. 对换性

对换性是指允许在作业的运行过程中进行换进、换出,亦即,在进程运行期间,允许将那些暂不使用的程序和数据,从内存调至外存的对换区(换出),待以后需要时再将它们从外存调至内存(换进);甚至还允许将暂时不运行的进程调至外存,待它们重又具备运行条件时再调入内存。

  1. 虚拟性

虚拟性是指能够从逻辑上扩充内存容量,使用户所看到的内存容量远大于实际内存容量。这是虚拟存储器所表现出来的最重要的特征,也是实现虚拟存储器的最重要的目标。

4.7 请求分页存储管理方式

4.8 页面置换算法

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2019 Acan's blog All Rights Reserved.

访客数 : | 访问量 :