Operating System Concepts (6th Edition)2017高考时间
非诚勿扰刘婷婷近况
第三章操作系统结构
梦见山崩地裂
更新日期:2005.3.21
操作系统提供了程序执行的环境。各种操作系统的内部构成相当不同,它们沿着一些不同的思路组织。新的操作系统的设计是重大的工作(major task)。设计之前必须要明确定义系统目标,针对所期望的系统类型选择算法和策略。
可以从几个有利的位置来观察一个操作系统。首先是分析它所提供的服务。其次是分析它向用户和程序员提供的接口。最后是分析系统组件和这些组件之间的联系。本章我们将研究操作系统的这三个特征,并展现用户、程序员以及操作系统设计者的观点。我们要考虑:操作系统提供了什么样的服务、它是怎样提供这些服务的,以及设计这样的系统需要什么样的方法学理论。
3.1 系统组件
构造像操作系统这样大型的复杂的系统就必须要把它划分成许多小块(piece,可以理解为子系统)。每一小块必须是系统某一部分的详细定义,包括输入、输出和功能。显然,不是所有的系统都有着同样的结构。然而许多现代操作系统有着同样的目标,就是支持从3.1.1节到3.1.8节所列出的系统组件。
3.1.1 进程管理
程序本身并不能做什么,只有在CPU执行它的指令时才能有所作为。可以把进程看作是正在运行的程序,但是当我们进一步研究时,对进程的定义将更为普遍。一个分时用户程序(如编译器)是一个进程。个人用户在PC上运行的字处理程序是一个进程。一个系统任务(如输出到打印机)也是一个进程。现在,我们认为进程是一个作业或分时程序,但是,稍后你将明白这个概念更加普遍。在第四章中将会看到我们可以提供允许进程创建与其并发执行的子进程的系统调用
进程需要特定的资源(包括CPU时间、内存、文件和I/O设备)来完成工作。这些资源或者在进程创建时分配给它,或者在其运行时。除了在进程创建时所获得的各种物理资源和逻辑资源以外,各种各样的初始化数据(或输入)也可能一同传送给进程。例如,考虑一个能够在终端的显示屏上显示一个文件状态的进程。这个进程将获得包含输入的文件名,并且将执行相应的指令和系统调用来获取所期望的信息并显示在终端上。
我们着重强调程序本身不是进程;程序是静态实体(passive entity)(像是存储在磁盘中的文件的内
容),而进程是动态实体(active entity),它用一个程序计数器来指明要执行的下一条指令。进程必须要按顺序执行。CPU执行完进程的一条指令后再执行下一条,直到进程结束。更进一步讲,一次最多执行一条代表该进程的指令。这样,从来就不会出现两个独立运行的序列。一个程序在运行时创建多个进程是非常普遍的。
在系统中,进程是工作单元。这样的系统由进程集合构成,有些是操作系统进程(那些执行的系统代码),其它的是用户进程(那些执行的用户代码)。通过对CPU的多路复用,所有的这些进程可以被并发执行。
操作系统要负责下列与进程管理相关的工作:
·创建和撤销用户及系统进程
·挂起和恢复进程
·提供进程同步机制
·提供进程通信机制
·提供死锁处理机制
我们将在第四章到第七章中讨论进程管理。
3.1.2 主存储器管理
就像我们在第一章中所讨论的,主存储器是现代计算机系统运行的核心。主存储器是由字或字节组成的大型队列,容量在数十万到数十亿之间。每个字或字节都有它自己的地址。主存储器是CPU和I/O设备共享的大容量快速存储器。中央处理器在取指令周期中从主存储器中读取指令,而且在取数据周期中从主存储器中读写数据。通过DMA,I/O操作也实现了对主存储器的数据读写。通常主存储器是CPU唯一能
够直接寻址和访问的大容量存储空间。例如,CPU要处理磁盘中的数据,那么CPU首先发出I/O调用将这些数据传送到主存储器中。同样,指令必须在存储器中才能够由CPU执行。
必须要把程序映射到绝对地址并载入内存中才可以执行。在程序运行时,它通过产生绝对地址来从内存中访问程序指令和数据。最后,程序结束,它将释放所占内存空间,下一个程序能够被载入并执行。
为了提高CPU利用率和计算机响应速度,我们必须在内存中保留多个程序。有许多不同的内存管理策略,而且不同算法的效率取决于具体的环境。为具体的系统选择内存管理策略要考虑到许多因素——尤其是系统的硬件设计。每种算法都需要自己的硬件支持。
操作系统要负责下列与内存管理相关的工作:
·跟踪内存使用情况,明确哪一部分正在使用和为谁所用
·在内存空间有效时决定将哪个进程载入内存
·根据需要分配和释放内存空间
将在第九章和第十章中讨论内存管理技术。
3.1.3 文件管理
文件管理是操作系统中可视性最强的组件之一。计算机能够将数据存储在各种类型的物理介质上。磁带、磁盘和光盘是最常用的介质。每种介质都有自己的特性和物理结构。每个存储媒体由一个驱动器控制(如磁盘驱动器或磁带驱动器),这种驱动器也有自己的独有特性。这些特性包括访问速度、容量、数据传输率和存取方式(顺序的或随机的)。
为了便于使用计算机系统,操作系统提供了一个计算机系统的整体逻辑层面。操作系统把存储设备的物理属性抽象定义为一个逻辑存储单元——文件。文件被映象到物理媒介中,通过存储设备来访问这些文件。
文件是由其创建者定义的相关信息的集合。一般的文件表现为程序(源程序和目标代码)和数据。数据文件可能是数字的、字母的或二者混合的。文件可能是形式自由的(如文本文件),也可能有严格定义的格式(如固定字段)。(Files may be free-form (for example, text files), or may be formatted rigidly (for example, fixed fields).)由字、字节、行或记录组成的文件结构是其创建者定义的。文件概念具有相当广泛的含义。
操作系统通过管理大量存储体(如由驱动器控制的磁盘和磁带)实现了文件的抽象概念。另外,为了更简易的使用文件,通常将他们组织到目录中。最后,如果有多个用户访问文件,我们可能需要控制谁以什么样的方式访问(例如:读、写、追加)。
操作系统要负责下列与文件管理相关的工作:
·创建和删除文件
·创建和删除目录
·将文件映象到辅助存储器中
李现被鱼亲吻
·将文件备份到永久(非易失性)存储体中
我们将在第十一章和第十二章中讲述文件管理技术。
3.1.4 I/O系统管理
操作系统的目的之一就是要向用户隐藏具体的硬件特性。例如,在UNIX中,通过I/O子系统向操作系统本身隐藏了I/O设备的特性。I/O子系统由以下几个方面组成:
·一个内存管理模块,这包括:buffering、caching和spooling
·一个通用设备驱动程序接口
·针对具体硬件设备的驱动程序
只有设备驱动程序了解所指定的具体设备特性。
在第二章中我们讨论了高效的I/O子系统结构是如何应用中断处理程序和设备驱动程序的。在十三章,我们将讨论I/O子系统怎样与其它的系统模块相连、怎样管理设备、怎样传输数据和怎样探测I/O操作结束。
3.1.5 辅助存储器管理
操作系统的主要目的是执行程序。这些程序在运行时(以及它们要访问的数据)都必须在主存储器中。
因为主存储器的容量太小不能存储所有的程序和数据,而且掉电后会丢失所有的存储信息,所以计算机系
统必须要提供辅助存储器作为主存储器的后备。大多数现代计算机系统使用磁盘作为存储程序和数据的主要联机存储体。大多数程序(包括编译程序、汇编程序、排列程序、编辑程序和格式化程序)在载入内存之前存储在磁盘上,并且在运行时利用磁盘存储它们所处理的源文件和目标文件。因此,合理的磁盘管理对一个计算机系统来说是至关重要的。
操作系统要负责下列与辅助存储器管理相关的工作:
·空闲空间管理
·空间分配
·磁盘调度
因为频繁的使用辅助存储器,所以必须要能够高效运行。计算机的整体运行速度取决于磁盘子系统的速度和该子系统的实现算法的效率。将在第十四章讨论辅助存储器管理。
3.1.6 网络管理
分布式系统是一个处理机的集合,这些处理机既不共享内存和外围设备,也不共享时钟。而是每个处理机拥有自己的本地内存和时钟,并且这些处理机可以通过各种通信线路(如高速总线或网络)进行通信。一个分布式系统中的处理机在规模和功能上有所不同。其中可能包括小型微处理器、工作站、小型机和大型通用计算机。
在(分布式)系统中,处理机通过通讯网络相连接,有多种不同的方法可以配置该网络。这种网络可以完全或部分的连接。通信网络的设计必须要考虑到报文路由选择和连接策略,以及争用和安全的问题。
分布式系统将物理上相互独立的可能不同种类的系统集合成为一个独立相连的系统,向用户提供了访问由系统维护的各种资源的能力。对共享资源的访问加快了计算速度、增强了系统功能、提高了数据的可用性并加强了可靠性。操作系统把网络细节包含在了网络接口设备驱动程序中,于是将网络访问泛化为一种文件访问的形式。(Operating systems usually generalize network access as a form of file access, with the details of networking being contained in the network interface’s device driver.)分布式系统所使用的协议在很大程度上影响到系统的效用和普及。环球网的创新在于为信息共享提供了新的途径。它改进了现有的文件传输协议(FTP)和网络文件系统(NFS),去掉了用户必须登陆才能访问远程资源的限制。环球网定义了一个新的协议——超文本传输协议(http),它用于在web服务器和web浏览器之间进行通信。一个web浏览器只需要向远程机器的web服务器发送一个信息请求,
然后获得返回信息(文本、图片、指向其它信息的链结)。这种在易用性上的提高促进了http和Web应用的快速成长。
我们将在第十五章到第十七章中讨论网络和分布式系统。
3.1.7 系统保护
如果一个计算机系统有多个用户并允许并行执行多个进程,那么必须要保护各个进程免受其它进程的侵扰。为此,需要提供一种机制来保证只有那些从操作系统获取了合适权限的进程能够操作文件、存储段、CPU和其它资源。
邓文迪个人资料例如,内存寻址硬件确保了一个进程只能在自己的地址空间内执行。计时器确保进程最终能够放弃对CPU的控制。用户不能够访问设备控制寄存器,这样就保护了各种外围设备的完整性。
保护是由操作系统定义的控制程序、进程或用户访问的机制。这个机制必须要提供一种方法来描述要施加的控制,以及强制执行的方法。
通过检测子系统接口中潜伏的错误,保护能够增强系统的可靠性。对接口错误的早期检测常常能够阻止一个子系统故障波及到其它正常的子系统。一个未受保护的资源难以防止未授权或不适当的用户的使用(或误用)。一个面向保护的系统提供了一种区分经授权的和未授权的使用的方法,这将在第十
八章中讨论。
一寸照片尺寸3.1.8 命令解释程序
命令解释程序是操作系统中最重要的系统程序之一,它是用户和操作系统间的接口。有些操作系统在内核中包含了命令解释程序。其它的操作系统(像DOS和UNIX)把命令行解释器当作一个特殊的程序,(在分时系统中)当一个用户登陆到系统或初始化一个任务时,它就已经在运行了。
许多命令是通过控制语句提供给操作系统的。(Many commands are given to the operating system by control statements.)当批处理系统中的一个新作业开始时,或当一个用户登录到分时系统中时,一个读取
并解释控制语句的程序会自动运行。这个程序有时被称为控制卡片解释程序或命令行解释程序,而且经常被称为shell。它的功能很简单:获取下一条命令语句并执行。
通常操作系统在命令解释程序方面的差别很大,一个用户界面友好的命令解释程序会使操作系统更容易为一些用户所接受。用户界面友好的一个风格是用在Macintosh和Microsoft Windows中的基于鼠标的窗口菜单系统(mouse-based window-and-menu system)。可以移动鼠标的位置以指向图像、图标,或屏幕(屏幕用于显示程序、文件和系统功能)上。根据鼠标指针的定位,单击鼠标上的按钮可
以执行一个程序、选择文件或目录(被称为文件夹)或弹出一个包含命令的菜单。有些用户喜欢功能更强大更复杂也更难掌握的命令解释程序。在这些命令解释程序中,通过键盘键入命令并在屏幕上显示或在终端上打印出来,然后通过“enter”(或“return”)键向命令解释程序发出信号,告知一条命令输入完成并等待运行。MS-DOS 或UNIX命令解释程序就是以这种方式执行。
命令语句本身负责进程的创建和管理、I/O管理、辅助存储器管理、主存储器管理、文件系统访问、保护和网络。
3.2 操作系统服务
操作系统提供了程序运行的环境。它为程序和程序用户提供了特定的服务。当然,不同的操作系统提供的具体服务不同,但是我们能够出其共同部分。提供的这些操作系统服务是为了便于程序员设计程序。
·程序执行:系统必须要能够将程序载入内存并运行它。程序必须能够正常的或异常的(指示错误)结束运行。
·I/O操作:一个正在运行的程序可能要请求I/O操作。这可能会涉及到文件或I/O设备。针对具体的设备,需要特定的功能(如倒卷一个磁带驱动器或清空一个CRT屏幕显示)。出于系统效率和保护的原因,用户通常不能够直接控制I/O设备。因此,操作系统必须要提供一种I/O运行机制。
·文件系统处理:文件系统相当有意思。显然,程序需要能够读写文件,也要能够创建和删除文件。
·通信:在很多情况下,一个进程需要与另外一个进程交换信息。这种通信可以通过两种主要的方式。第一种方式是在运行在同一台计算机上的进程间通信;另外一种是在运行在由一个计算机网络连接的不同的计算机系统上的进程间通信。可以通过共享存储器或报文传送(这种方式中,操作系统在进程之间将信息打包移动)的方式实现进程间的通信。
·错误检测:操作系统需要经常注意可能发生的错误。错误可能发生在CPU和内存(如存储错误或电源故障)、I/O设备(如磁带奇偶检验错误、连结网络失败或打印机缺纸)以及用户程序(如运算溢出、试图访问非法存储器地址或过多占用CPU时间)中。对于每种类型的错误,操作系统应该能够采取针对性措施以确保计算的正确性和相容性。
另外,存在着另外一些操作系统功能,它们不是为了帮助用户工作,而是为了确保系统本身的高效运行。通过在多个用户间共享计算机资源,多用户系统能够获得高运行效率。
·资源分配:当多个用户登录到系统中或同时有多个作业运行时,必须要在它们之间分配资源。操作系统管理许多不同类型的资源。有些资源(如CPU周期、主存储器和外存储器)可能有专用的分配代码,而其它的(如I/O设备)可能有更通用的请求和释放代码。例如,在决定如何最好的使用CPU的问题上,操作系统的CPU调度程序要考虑到CPU速度、必须要执行的作业、有效的寄存器数量和其它的
一些因素。也可能有一些程序用于向作业分配磁带驱动器。一个这样的程序定位一个未用的磁带驱动器并将该设备的新用户记录在内部表中。其它的程序用于清空这个表。这些程序也能够分配绘图仪、调制解调器和其它外围设备。
·账户管理:我们希望跟踪记录每个用户使用哪些类型的计算机资源和用了多少。这个记录保持可能用于记账(以便用户付账)或简单的用于累加使用率统计。对于研究者来说,使用率统计可能是个有效的工具。利用使用率统计,研究者可以重新配制系统以改善计算服务。
·保护:存储在多用户计算机系统上的信息的所有者希望能够控制对该信息的使用。当多个不相关的进程并发执行时,一个进程不应该能够干扰其它进程或操作系统本身。保护包括了监控所有对系统资源的访问。对来自外界的系统安全检测(security)也是非常重要的。这种保护往往通过密码的方式,用户向系统验证口令才能访问资源。它也包括了保护外部I/O设备(包括调制解调器和网络适配器)免于非法的访问企图和记录所有这样的非法闯入。如果一个系统受到保护并且是安全的,那么就必须要建立预防措施。
系统的安全强度只与其最薄弱的一环有关。(A chain is only as strong as its weakest link.)
3.3 系统调用
系统调用提供了进程和操作系统间的接口。这些调用通常是以汇编语言的形式,而且它们通常会在汇编语言程序员的使用手册中列出来。
某些系统允许高级语言直接进行系统调用,这通常是将系统调用预定义为函数或子程序调用。它们调用一个指定的运行时程序(run-time routine),这个程序完成系统调用,或者直接在代码里加入系统调用。
有些语言(如C、C++和Perl)已经取代了汇编语言进行系统程序设计。这些语言允许直接进行系统调用。例如,在C或C++程序中可以直接调用UNIX系统调用。Microsoft Windows平台中的系统调用是Win32应用程序接口(API)的一部分,Win32 API可以用于所有针对Microsoft Windows的编译器。
作为一个使用系统调用的例子,考虑一个简单的程序,它从一个文件中读取数据并将数据拷贝到另外一个文件中。这个程序首先需要获得这两个文件的文件名:输入文件和输出文件。指定文件名的方法有很多种,这要看具体的操作系统。一种方法是由程序向用户询问这两个文件的名称。在交互式系统中,这种方法将请求一系列系统调用:首先在屏幕上写出提示信息,然后读取键盘的输入字符(这些字符指定了两个文件)。在基于鼠标的窗口菜单系统中,一个名为“文件”的菜单通常显示在窗口上。用户可以使用鼠标选择源文件名,并且能够打开一个类似的窗口用于指定目标文件。
一旦获得了这两个文件名,这个程序就要打开输入文件并创建输出文件。这些操作的每一步都需要请
求另外的系统调用,并可能会出现错误。当这个程序尝试打开输入文件时,它可能会发现没有这个名字的文件存在或文件被访问保护。在这种情况下,程序必须在控制台上打印出一段消息(要用到另外的系统调用),或者我们删除现存的文件(也要用到另外的系统调用)并创建一个新文件(又要用到另外的系统调用)。在交互式系统中,程序会询问用户是替换现有文件还是终止程序。
现在两个文件都建立起来了,接下来,我们从输入文件中循环的读出数据(用到一个系统调用),然后写入输出文件(用到另一个系统调用)。每个读写操作必须要返回状态信息以便于考虑各种可能出现的错误。在输入过程中,程序可能会发现到达文件末端或在读取时发生了硬件故障(比如奇偶校验错误)。在输出过程中,依据不同的输出设备,可能会发生各种错误(比如,磁盘空间不足,磁带末端,打印机缺纸)。
最后,在完成对整个文件的拷贝之后,程序就需要关闭这两个文件,向控制台中写一段消息(需要另外的系统调用)并最终正常结束(最后的系统调用)。正如我们所看到的,即使是一个简单的程序也可能要调用大量的系统调用。
然而大多数用户从未见到过这些细节。运行时(run-time)支持系统(功能构件在库中,并且包含一个编译器)为高级语言提供了更为简洁的接口。例如,C++中的cout语句被编译为一条对run-time支持程序的调用,该程序进行必要的系统调用,检查错误并最终将结果返回给用户程序。这样,编译器和run-time 支持包向程序员隐藏了操作系统接口的大部分细节。
根据对计算机的使用情况,有多种方式可以进行系统调用。在进行系统调用时通常需要更多的信息,而不仅仅是系统调用的标识。根据具体的操作系统和系统调用,所需的信息类型和数量不尽相同。例如,为了获取输入,我们可能需要指定文件或设备作为信息来源,并且要把地址和内存缓冲区的长度放到输入读取的位置。(For example, to get input, we may need to specify the file or device to use as the source, and the address and length of the memory buffer into which the input should be read.)当然,设备或文件以及长度可能隐含在调用中。
有三种通用的方法可以向操作系统中传送参数。最简单的方法是将参数传送到寄存器中。然而,在某些情况下寄存器存不下所有的参数。这样,通常将参数存储到内存中的块或表中,然后将内存块的地址作为参数传送到寄存器中(图3.1)。Linux采用了这种方法。也可以使程序将参数放置或推入堆栈中,然后由操作系统从堆栈中弹出。有些操作系统更喜欢利用块或堆栈,因为这些方法没有限制参数的数量和长度。