多处理器操作系统实现中存储器和通信的二重性

摘要

Maeh是卡耐基梅隆大学正在实现的一个多处理器操作系统。Mach设计的一个重要组成部分是内存对象的使用,它既可以由内核管理,也可以由用户程序通过消息接口管理。该特性允许事务管理系统等应用程序参与二级存储管理和页面替换的决策。
本文探讨了Mach及其外部内存管理设备的目标、设计和实现。Mach中的内存和通信之间的关系被检查,因为它涉及到整体性能,数学的新多处理器架构的适用性,以及应用程序的结构。

1. Introduction

1984年底,我们开始实施一种叫做“多”的操作系统。我们对Maeh的目标是:
·一个面向对象的接口,包含少量的基本系统对象,
·支持分布式计算和多处理,
•可移植性广泛的多处理器和单处理器架构,
•兼容伯克利UNIX,和
•性能可与商业UNIX产品相媲美。

这些早期目标大多已经实现。基础的数学内核是基于五个相互关联的抽象;通过消息传递调用Math对象上的操作。Mach在计算机科学系的大多数工作站和大型机上运行,支持分布式计算和并行处理项目,如Camelot分布式事务处理系统[21]、Agora并行语音理解系统[3]和OPS5[7]的并行实现。
Mach已经被移植到十多个计算机系统中,包括单处理器和多处理器VAX家族的十个成员,IBM RT PC, SUN 3, 16处理器的Encore MultiMax和26处理器的sequentbalance 21000。Mach与Berkeley是二进制兼容的
UNIX 4.3bsd,并且在几个总体系统性能基准([1])中显示优于4.3bsd。

Much设计中一个关键且不同寻常的元素是这样一个概念:通信(以消息传递的形式)和虚拟内存可以发挥互补的作用,不仅在分布式和并行应用程序的组织中,而且在操作系统内核本身的实现中。Mach使用内存映射技术使紧密耦合的多处理器或单处理器上的大型消息传递更加高效。另外,Mach通过将进程地址映射到内存对象上实现了虚拟内存,这些对象被表示为通信通道,并通过消息访问。Math将内存和通信作为对偶处理的优势包括:
·增加了用户程序可用的内存管理灵活性,
•Mach设施与紧密耦合和松散耦合多处理器之间的更好匹配,以及
•改善性能。

本文描述了Mach中存储器与通信的关系。特别地,我们研究了关键Mach内存管理操作的设计和实现,应用程序如何在Mach内核之外管理Math内存对象,以及Math操作系统的整体性能。

2. Early Work in Virtual Memory/Message Integration

Mach的设计很大程度上归功于CMU之前开发的一个叫做Accent[15]的系统。Accent的一个主要特点是集成了虚拟内存和通信。通过使用内存映射技术,在Accent中可以以极高的性能在进程之间传输大量数据。这允许客户机和服务器进程交换潜在的巨大数据对象,例如大文件,而不用担心消息传递的传统数据复制成本。
实际上,埃森哲将I/O可以通过虚拟内存管理来执行的概念引入了消息传递系统领域。它支持单级存储,其中主存储器充当二级存储器的缓存。文件系统数据和rtmtLme分配的存储都实现为基于磁盘的数据对象。使用影子分页技术管理大型消息的副本。当时的其他系统,如IBM System 38[6]和Apollo Aegis[13],也使用了单级存储方法,但将其应用局限于ide的管理。
对于操作系统设计者来说,单一级别的存储可能非常有吸引力。通过允许程序员将文件映射到进程的地址空间,它可以简化应用程序的构造。这通常鼓励用概念上更简单的程序语言结构(如数组和记录)来替换I/O例程的状态库(如UNIX标准I/O包)。单级存储也可以使程序更高效。文件数据可以直接读入用于实现程序的虚拟地址空间的物理内存页,而不是读入由操作系统管理的中间缓冲区。由于物理内存用于缓存辅助存储,因此经常可以重复引用相同的数据,而不需要相应的磁盘传输。
Accent成功地展示了将内存映射与消息传递结合在一起的实用价值。在巅峰时期,它在CMU的150多个工作站上运行,并作为一系列实验的基础,包括分布式事务处理[20]、分布式传感器网络[8]、分布式文件系统[12]和进程迁移[24]。

然而,Accent在新硬件架构的引入中并没有成功地生存下来,而且它从未能够有效地支持学术社区[16]中使用的大量UNIX软件。此外,从系统设计师的角度来看,消息/内存集成的Accent风格缺乏对称性。重音允许使用内存映射技术来管理通信,但是虚拟内存对象的概念是高度专门化的,这样的对象的管理很大程度上由操作系统本身保留。这个问题通过实现虚拟段[24]得到了部分解决,虚拟段可以由用户状态进程提供,但是这样的对象没有内核数据对象的灵活性和性能。

3. T h e M a c h Design

Mach设计的初衷是将Accent从单处理器的网络操作系统转变为支持高速网络连接的多处理器和单处理器的新环境。它的历史导致了一种设计,既提供了Accent中流行的消息传递,又提供了对并行处理和共享内存的新支持。
Mach从Accent继承了四个基本的抽象概念(尽管有很大的改变):任务、线程、端口和消息。它们的主要目的是提供控制程序执行、内部程序虚拟内存管理和进程间通信。此外,Mach还提供了第五个抽象,称为内存对象,辅助存储管理是围绕内存对象构建的。正是Math内存对象抽象使Mach与Accent区别开来,并使Mach能够有效地管理系统服务,如网络分页和内核外的文件系统支持。

3.1. Execution Control Primitives

在Mach中,程序的执行是通过使用任务和线程来控制的。任务是资源分配的基本单位。它包括一个分页虚拟地址空间和对系统资源(如处理器和通信能力)的受保护访问。线程是基本的计算单元。它是一个在任务中操作的轻量级进程;它唯一的物理属性是它的处理状态(例如,程序计数器和寄存器)。任务中的所有线程共享该任务的地址空间和功能。

3.2. Inter-Process Communication

Mach中的进程间通信(IPC)是根据端口和消息定义的。这些构造提供了位置独立性、安全性和数据类型标记。
端口是一个通信通道。逻辑上,端口是内核保护的消息的有限长度队列。通过接收包含端口功能(发送或接收消息)的消息来授予对端口的访问权。一个端口可以有任意数量的发送端,但只有一个接收端。
消息由固定长度的消息头和可变大小的类型化数据对象集合组成。只要类型正确,消息可能包含端口功能或嵌入指针。一条消息可以传输到一个任务的整个地址空间。端口的基本基本操作是发送和接收消息。表3-1列出了这些原语。除了这些原语和一些返回调用任务或线程标识的函数外,所有Mach设施都用端口上的远程过程调用来表示。
Mach内核本身可以被认为是一个多线程控制的任务。内核任务actsasaserver反过来实现任务和线程。创建任务或线程的行为返回发送访问权限到一个端口,该端口代表新的任务或线程,可以用来操作它。发送到这样一个端口的消息会导致对它所代表的对象执行操作。以这种方式使用的端口可以看作是面向对象系统[10]中对象的功能。发送消息(以及接收回复)的行为对应于基于功能的系统(如Hydra[23]或StarOS[11])中的跨域过程调用。
消息传递提供的间接方式允许对象在网络中任意放置,而不需要考虑编程细节。例如,一个线程可以通过向表示另一个线程的端口发送一个暂停消息来暂停另一个线程,即使请求是在网络中的另一个节点上发起的。因此,可以在不同类型的机器上运行不同的系统配置,同时为所有资源提供一致的接口。在任何特定机器上运行的实际系统更多的是其服务器的功能,而不是其内核。
任务分配端口来表示自己的对象或执行通信。任务也可以释放其对端口的权限。当一个端口的接收权限被销毁时,该端口也将被销毁,并通知拥有发送权限的任务。端口权限管理和消息接收控制的操作如表3-2所示。

3.3. Virtual Memory Management

任务的地址空间由有效内存区域的有序集合组成。任务可以在底层硬件定义的虚拟地址空间的任何地方分配内存区域2。Mach施加的唯一限制是区域必须在系统页面边界上对齐。系统页面大小是一个启动时间参数,可以是硬件页面大小的任意倍数。
Mach支持在具有共同祖先的任务之间通过继承实现读写内存共享。当一个子任务被创建时,它的地址空间可以共享(读/写)或复制父任务地址空间的任何区域。与Accent中一样,写时复制共享用于在任务创建和消息传输期间高效地执行虚拟内存复制。表3-3总结了任务可以执行的虚拟内存操作的全部集合。

3.4. External Memory Management

马赫策略的一个重要部分是对二次存储基本概念的重新设计。Mach没有将辅助存储建立在内核提供的文件系统的基础上(就像在Accent和Aegis中所做的那样),而是以与通过消息传递可访问的其他服务器提供的资源相同的方式来处理辅助存储对象。这种形式的外部内存管理允许普通用户状态服务器使用单层存储的优点。
Mach外部内存管理接口是基于Mach内存对象的。与Math环境中的其他抽象对象一样,内存对象由端口表示。与其他Mach对象不同,内存对象不是由Mach内核单独提供的,而是可以由用户级数据管理器任务创建和服务。内存对象是一个抽象对象,表示一组数据字节,在这些数据字节上定义了若干操作(如读、写)。数据管理器完全负责这些数据的初始值,并在必要时对数据进行永久存储。Mach内核对内存对象的用途没有任何假设。
为了使内存对象数据以物理内存的形式对任务可用,Mach内核充当内存对象内容的缓存管理器。当内核当前没有有效的缓存常驻页的页面错误发生时,将对请求该数据的内存对象进行远程过程调用。
当缓存已满时(即所有物理页都包含其他有效数据),内核必须选择一些缓存页来替换。如果该页中的数据在物理内存中被修改,则必须刷新该数据;同样,对内存对象进行远程过程调用。类似地,当所有任务地址映射中对一个内存对象的引用被释放时,内核释放该对象的缓存页供其他数据使用,必要时清理它们。
由于历史原因,外部内存管理接口已经被用于内核活动,即分页。因此,术语分页对象经常用于指内存对象,术语paper经常用于描述实现内存对象的数据管理器任务。

3.4.1. Detailed Description

数据管理器任务与Mach内核之间的接口由三部分组成:
应用程序将内存对象映射到其地址空间的调用。如表3-3所示。
•内核对数据管理器的调用。接口总结如表3-5所示。
•数据管理器在Mach内核上调用它的内存对象。操作总结如表3-6所示。

与其他Mach接口一样,这些调用是使用IPC实现的;每个调用的第一个参数是请求发送到的端口,并表示操作将影响的对象。

通过使用vmallocate_with_pager原语指定内存对象(端口),可以将内存对象映射到应用程序任务的地址空间。一个内存对象可以被映射到不止一次,可能是在不同的任务中。vm_allocate_with_pager调用中由address指定的内存区域将被映射到内存对象中指定的偏移量。进入内存对象的偏移量不需要在系统页面边界上对齐;然而,Mach内核将只保证具有相似页面对齐的映射之间的一致性。

当被要求第一次映射内存对象时,内核通过对内存对象进行page_init调用作出响应。这条信息包括:
寻呼机请求端口,数据管理器可用于对Mach内核进行缓存管理请求;
在vm_regions calls3返回的描述中,内核将使用一个分页名称端口来将这个内存对象标识给其他任务。
Math内核持有对内存对象端口的发送权限,以及对寻呼机请求和寻呼机名称端口的发送和接收权限。
如果一个内存对象映射到不同主机(具有独立的Mach内核)上多个任务的地址空间,数据管理器将从每个内核接收一个初始化调用。为了进行标识,内核在以后的操作中指定寻呼机请求端口。
为了处理缓存丢失(即页面错误),内核发出一个pager_data_request调用,指定所需的范围(通常是单个页面)和分页请求端口,数据应该重命名到该端口。
要清除脏页,内核执行一个pager_data_writall调用,指定内存对象中的位置,并包括要写入的数据。当数据管理器不再需要数据时(例如,数据已成功写入二级存储),它将使用虚拟机。释放缓存资源。
这些由Mach内核进行的远程过程调用是异步的;这些调用没有显式的返回参数,内核也不等待确认。
数据管理器通过使用pager_data_provided调用将内存对象的数据传递给内核。这个调用指定数据在内存对象中的位置,并包括内存对象数据。它通常用于响应内核对数据管理器的pagerdatarequest调用。
典型的数据管理器只会按需提供数据(在处理pagerdatarequest调用时);但是,高级数据管理器可以提供比要求更多的数据。Mach内核在任何一次调用中只能处理系统页面大小的整数倍,并且会丢弃部分页面。
由于数据管理器可能对其内存对象的一致性有外部约束,Mach接口提供了一些控制缓存的功能;这些调用是使用初始化时提供的寻呼机请求端口进行的。
pager_flush_request调用会导致内核使相关数据的缓存副本失效,必要时回写修改。pager_clean_request调用请求内核回写修改,但允许内核继续使用缓存的数据。内核在响应中使用pager_data_write调用,就像启动缓存替换一样。
数据管理器可以通过发出pager_data_lock请求来限制缓存数据的使用,并指定必须防止的访问类型(读、写和执行的任何组合)。例如,数据管理器可能希望暂时允许对缓存数据进行只读访问。当数据管理器认为有必要时,可以更改页面上的锁定。[为了避免竞争条件,pager_dataprovided调用还包括一个初始锁值。]
当用户任务需要比数据管理器所允许的更多的对缓存数据的访问时(例如,通过调用pager_data lock使页面变为只读的写错误),内核会发出一个pager_data_unlock调用。当数据管理器有能力更改对该数据的锁定时,它将做出响应。
当没有对内存对象的引用保留,并且所有修改都被写回内存对象时,内核将释放它对与该内存对象相关的三个端口的权限。数据管理器接收到销毁请求和指定端口的通知,此时它可以执行适当的关闭。
为了获得更好的缓存性能,数据管理器可以通过调用pager_cache来允许缓存内存对象的数据,即使在所有应用程序地址映射引用都消失之后。允许这样的缓存绝不是绑定;内核可以选择放弃对内存对象端口的访问,因为它认为它的缓存管理是必要的。数据管理器以后可能会取消缓存内存对象的权限。
Mach内核本身创建内存对象,为vm_allocate创建的零填充内存提供备份存储。内核分配一个端口来表示这个内存对象,并在pager_create调用中将其传递给默认的分页任务,该任务在系统初始化时间5时为内核所知。这个调用在形式上类似于pager_init;但是,它不能在内存对象端口本身上执行,而是在默认分页器提供的端口上执行。
由于这些内核创建的对象没有初始内存,因此默认分页器可能没有数据来响应请求。在这种情况下,它必须执行一个pager_data_unavailaball调用来指示页面应该是零填充的。

4. UsingMemoryObjects

本节简要介绍两个示例数据管理器及其应用程序。第一种是具有读/写时拷贝接口的文件系统,它使用内存管理接口的最小子集。第二段摘录自一致网络共享内存服务的操作。

4.1. A Minimal Filesystem

最低限度使用Mach外部接口的服务的一个例子是文件系统服务器,它提供了读取整个文件/写入整个文件的功能。虽然它很简单,但这种接口风格已经在实际的服务器中使用了[12,19],应该考虑一个严肃的例子。
一个应用程序可以这样使用这个文件系统:
注意,Is_read文件调用将返回新的虚拟内存。这个内存在应用程序的地址空间中是写时复制的;在进行随机更改时,其他应用程序将始终看到原始文件内容。应用程序必须显式地存储其更改。
为了处理fs_read_file请求,文件系统服务器创建一个内存对象,并将其映射到自己的地址空间。然后,它通过IPC机制返回该内存区域,以便将其映射到客户机的地址空间中,即写即拷。
当执行vm_allocate_with_pager调用时,内核将发出一个pager_init调用。文件系统必须在某个时候接收到这条消息,并且应该记录其中包含的寻呼机请求端口。
当应用程序第一次使用数据的一个页面时,它会生成一个页面错误。为了填补这个错误,内核为该页发出一个pager_data_request。为了实现此请求,数据管理器使用pager_data_provided调用进行响应。文件系统将永远不会接收任何pager_data_write或pagerdata_unlock请求。在应用程序处理-定位它的文件的内存副本后,文件系统将收到寻呼机请求端口的端口死亡消息。然后,它可以释放该文件的数据结构和资源。

4.2 一致网络共享内存摘录

在本小节中,我们将描述如何使用内存管理接口在不同主机上的两个客户端之间实现共享内存区域。图4-1显示了重要的消息流量。
为了使用共享内存区域,客户端必须首先请联系提供共享内存服务的数据管理器。在我们的示例中,第一个客户端请求了一个共享内存区域,该区域没有被任何其他客户端使用。共享内存服务器创建一个内存对象(即,分配一个端口)以引用该区域,并将该内存对象X返回给第一个客户端。
在不同主机上运行的第二个客户端稍后会请求相同的共享内存区域。共享内存服务器找到内存对象X,并将其返回给第二个客户端。

每个客户端使用vm_allocate_with_pager将内存对象X映射到其地址空间。当每个内核处理该调用时,它对内存对象X进行寻呼机初始化调用。共享内存服务器记录X的每次使用,以及这些使用的寻呼机请求和名称端口。注意,数学内核不等待来自共享内存服务器的回复,但在允许vm_allocate_with_pager调用完成之前执行pagerinit调用。还请注意,虽然只有一个内存对象端口(X),但每个内核都有不同的请求和名称端口。在本示例中,“共享内存服务器可能位于客户端的主机上,也可能位于另一个主机上。
在第二个名称中,每个客户机在共享内存区域的同一页上都有一个读错误。同一个页面可以映射到两个客户机中的不同地址。每个内核在X上发出一个pager_data_request,为X指定它自己的寻呼机请求端口。共享内存服务器在适当的请求端口上使用寻呼机data_provided调用进行响应。由于请求只需要读访问,所以共享内存服务器在返回数据时对数据应用写锁9。共享内存服务器还必须记录该页面的所有使用(即寻呼机请求端口)。
对X执行一个pagerdata_unlock调用,请求授予每个任务写操作。在允许写权限之前,共享内存服务器必须使该页的所有其他使用无效;它使用pager_flush_request调用完成此操作。一旦所有的读取器失效,服务器将使用不带锁的pager_data_lock授予第一个客户机写访问权。

5.实现细节

Mach内核中使用了四种基本数据结构来实现外部内存管理接口:地址映射、内存对象结构、常驻页面结构和一组页面退出队列。

5.1. Address Maps

与Accent中一样,任务地址映射是一个目录映射
许多有效地址中的每一个地址都指向一个内存对象和该内存对象内的偏移量。为每个范围存储的附加信息包括保护和继承信息。
为了说明通过继承的共享,Mach地址映射是两级的。一个任务地址空间由一个顶层地址映射组成;地址映射条目引用第二级共享映射,而不是直接引用内存对象。每个任务属性的更改(如保护和继承)存储在顶层映射中。由映射条目表示的虚拟内存的更改会反映在共享映射中;例如,一个vra写入一个由多个任务共享的区域的操作将发生在它们的所有任务映射引用的共享映射中。
然后是引用内存对象结构的第二级共享映射。作为一种优化,如果没有发生共享,顶层映射可能包含对内存对象结构的直接引用。
当处理vm_allocate_with_pager调用时,Math内核查找给定的内存对象端口,试图找到相关的内部内存对象结构;如果不存在,则创建一个新的内部结构,并执行page_init调用。一旦找到amemoryobjectstructureis,它就被插入到(顶级)任务地址映射中。注意,共享语义与继承情况不同,因为不涉及共享映射;尝试vm_write内存对象的一个映射只会替换该映射,而不是在其他也映射了该内存对象的任务中反映它。

5.2. Virtual Memory Object Structures

对于地址映射中使用的每个内存对象(或者数据管理器建议允许缓存的内存对象),都保留一个内部内存对象结构。这个结构的组成部分包括用于引用内存对象的端口,它的大小,对该对象的地址映射引用的数量,以及当没有地址映射引用时是否允许内核缓存内存对象。
将驻留页面结构的列表附加到对象上,以便在销毁对象时方便地释放与该对象关联的页面。

5.3. Resident Memory Structures

每个驻留页结构对应于物理内存的一个页,反之亦然。常驻页结构将内存对象和偏移量记录到对象中,以及数据管理器允许对该页的访问权限。这里还保存了硬件提供的参考和修改信息。通过内存对象和偏移量(虚拟到物理表)提供快速常驻页查找的接口被实现为通过常驻页结构链接的哈希表。

5.4 Page Replacement Queues

页面替换使用几个通过常驻页面结构链接的页面退出队列。活动队列包含当前正在使用的所有页面,按最近最少使用的顺序排列。

5.5. Fault Handling

Mach页面故障处理器是Mach虚拟内存系统的核心。当硬件试图引用一个没有有效映射或存在保护冲突的页面时,将调用内核错误处理程序。故障处理程序的职责如下(如图5-1):
有效性和保护——内核通过在其任务的地址映射中执行查找来确定故障线程是否具有对地址的所需访问权。这个查找还会得到一个内存对象和偏移量。
页面查找——内核试图在虚拟到物理哈希表中查找缓存页的条目;如果页面不存在,内核必须从数据管理器请求数据。
write -on- copy-一旦找到页面,内核将决定是否需要write -on- copy操作。如果任务需要写权限,而页面还没有被复制,则会创建一个新页面作为原始页面的副本。如果需要,内核还会创建一个新的影子对象。

硬件验证——最后,内核通知硬件物理映射模块新的虚拟到物理映射。
除了硬件验证之外,所有这些步骤都以与机器无关的方式实现。

6.外部内存管理的问题

6.1. 内存故障的类型

虽然外部内存管理的功能可以成为精心应用程序手中的强大工具,但如果使用不当,它也会带来一些健壮性和安全性问题。其中一些问题是:

数据管理器不返回数据。线程现在可能阻塞,等待另一个用户任务提供的数据,而该用户任务不会立即响应。IPC和内存管理之间的紧密互连使得在试图访问任何内存之前,很难(或仅仅是昂贵的)确定该内存的源是否具有恶意。

数据管理器释放已刷新的数据失败。数据管理器可能会在脏页调出后未能及时释放内存,从而对调出过程造成严重破坏。

数据管理器填充缓存。这与无法释放数据的数据管理器在本质上非常相似,但更容易检测和预防。

数据管理器更改数据。恶意数据管理器可能在每次缓存刷新时更改其数据的值。虽然这对于共享内存应用程序是一个优势,但对于在消息中接收(虚拟复制)数据的应用程序来说,这是一个严重的问题。

数据管理器支持它自己的数据。如果数据管理器在等待其提供的数据的页面错误中阻塞,则可能发生死锁。

幸运的是,有几种技术可以最小化这些潜在的问题:
任务可以使用vm_regions调用来获取关于其地址空间组成的信息。虽然这可以使一个任务避免在它提供的内存上死锁,但它不能防止两个或多个任务在其他任务提供的内存上死锁。

使用多线程处理数据请求也有助于防止死锁;任务中的一个线程可以为该任务中的另一个线程的数据请求提供服务。

不能容忍数据更改的服务器任务,或者必须确保所有必要的数据可用的服务器任务,可以使用单独的线程在继续之前将数据复制到安全内存中。

6.2. 处理内存失败

6.2.1. 沟通失败的类比

与外部数据管理器相关的潜在问题与通信失败非常相似。这实际上并不奇怪,因为外部数据管理器是使用通信实现的。通信故障问题的解决方案适用于外部数据管理器故障。
任务的地址空间通过两种基本方式被内存对象填充:显式分配(vm_allocate或vm_allocate_with_pager)或接收IPC通信系统中的数据。在第一种情况下,数据的来源被认为是可信的(要么是默认的分页器,要么是请求者已知的数据管理器)。使用在消息中接收的数据可以被视为试图显式接收该数据;唯一的区别是失败的时间和粒度。
为通信失败提供的相同选项可应用于内存失败:可以指定超时时间,在此之后内存请求将被中止;可以发送通知消息,以便另一个线程可以执行恢复;等待直到请求被填满。在超时后中止内存请求可能涉及提供由默认分页器支持的(零填充)内存,或者终止等待线程。

数据管理器对内存对象的破坏(即内存对象端口的释放)导致的失败模式类似于对端口的破坏:通知那些之前访问过该对象的任务,取消正在进行的请求。

6.2.2. The Default Pager

默认分页器通过以下几种方式管理内核创建的内存对象的后备存储:通过用户任务显式分配(vm_allocate);影子内存对象;用于换出数据的临时内存对象。与其他数据管理器不同,它是一个受信任的系统组件。

当缓存的数据被写回数据管理器时,这些页面被临时移动到一个新的内存对象中,当数据管理器放弃该内存时,该对象将被销毁。如果数据管理器没有在适当的时间内处理和释放数据,那么数据可能会被调出到默认的分页器。通过这种方式,内核不会被错误的数据管理器所耗尽。

因为到默认页导航器的接口与其他外部数据管理器相同,所以对辅助存储的性质没有基本的假设。例如,默认的页导航器可能使用本地磁盘、网络服务或两者的某种组合。此外,可以将新的默认分页器调试为常规数据管理器。

6.2.3. Reserved Memory Pool

为了执行分页操作,内核必须发送一个消息;为了发送消息,内核可能需要分配额外的内存。为了避免死锁,内核必须为自己保留一定数量的内存来进行分页。此外,数据管理器任务可能需要分配内存以管理分页请求。内核必须至少为默认分页器提供足够的内存来处理分页,并且出于性能原因,希望能够为合理的数据管理器任务提供足够的内存。
许多其他操作系统也遇到过这个问题。这些系统通常通过使用用于管理二级存储的算法的内部知识来解决问题。不幸的是,马赫内核没有这样的知识;它必须依赖于对默认分页器执行分页操作所需内存量的保守估计。

7. 多处理器的问题

随着更快的网络和连接更松散的多处理器的建立,使用共享内存和作为通信机制的消息传递之间的区别正在变得模糊。有三种主要类型的多指令、多数据流(MIMD)多处理器已获得商业认可:

  1. 具有完全共享内存和几乎统一内存访问时间的统一内存访问多处理器(uma);
  2. 具有共享内存的非均匀内存访问多处理器(NUMAs),其中单个CPU可以快速访问一些内存,而较慢地访问另一些内存;而且
  3. 没有远程内存访问(NORMAs),基于消息的多处理器,通过内部或外部网络通信。

UMA系统在商业市场中是最普遍的。它们是三种类型中最容易使用的,因为它们与传统的多程控单处理器最相似。共享内存通常是在某种共享总线上提供的,各个cpu通过缓存访问总线。同步缓存内容。一个CPU的写操作将更新或刷新对其他CPU可见的适当缓存块。访问时间几乎是一致的,尽管缓存刷新可能导致某些算法的内存访问时间不一致,这取决于体系结构。uma的例子有Encore MultiMax, sequence Balance, VAX 8300和VAX 8800。

一些最早的多处理器是numa的例子,包括CMUs C.mmp[23]和CM*[11]。uma的一个问题是,它们经常依赖于一个共享的全局总线,这限制了可以附加的处理器和内存单元的最大数量。numa通常通过将一个本地内存与每个CPU关联来避免这个规模问题。该内存可以被其他cpu访问,但其时间开销只高于本地内存访问。典型的cpu - cpu互连是一个具有多层内部交换节点的通信交换机。虽然这样的开关可以容纳大量的通信处理器,但它们增加了NUMA远程内存访问延迟的特性。保持缓存内容一致的困难通过这样
开关导致大多数NUMA设计器(1)不提供缓存内存,(2)只允许对非共享内存进行缓存,或(3)提供智能编译器使用的指令级缓存控制。BBN Butterfly[2]是商业NUMA的一个例子。在Butterfly中,cpu之间的通信是通过Butterfly Switch实现的,其复杂性仅随处理器数量的对数增加而增加。Butterfly不使用缓存内存,远程访问时间大约是本地访问时间的10倍。因为NUMA架构允许在一台机器上放置更多数量的cpu,许多实验性的非常大的多处理器都是NUMA;512处理器的IBM RP3就是最近的一个例子。

norma是最容易构建的多处理器,从某种意义上说,只要有局域网,它就已经存在了。典型的NORMA由若干个在高速总线或网络上相互连接的cpu组成。互连拓扑取决于所使用的网络技术。例如,英特尔的HyperCube使用了一种以10MHz以太网作为连接技术的多级立方体结构。NORMAs与NUMAs的区别在于,它们不提供用于远程内存访问的硬件提供机制。通常,norma可以比numa大得多,但也比numa松散耦合得多。例如,在HyperCube上,远程通信时间以数百微秒计算,而在Butterfly上是5微秒,在MultiMax上则大大少于1微秒(平均)。

所有三种类型的多处理器都可以用来支持消息传递或共享内存。尽管一些制造商[4,9]已经为消息机制提供了硬件支持,但在单处理器和紧密耦合的多处理器上实现消息通信通常使用内部信号量和数据操作。在没有明确硬件支持的网络环境中,实现信息的参考复制[24]和读/写共享[13,14]是可能的。

正如Accent演示了写时复制可以用于单处理器中的消息传递一样,耶鲁大学的13演示了经过修改的Apollo Aegis内核可以支持需要在10MHz令牌环[14]上读写共享虚拟内存数据结构的应用程序。网络读/写共享是利用软件技术实现的,该技术与多处理器中一致缓存的硬件管理并行。缓存块(在这种情况下,由Apollo工作站的内存映射硬件映射的物理内存页)根据需要从全局内存中检索和缓存。允许在没有写入器的情况下进行多次读访问,但一次只允许一个写入器修改一页数据。

读取器试图写入以前读过的数据会导致内存错误,从而将读取器转换为写入器,并使所有其他页缓存失效。另一个工作站的后续读取尝试将导致写入器恢复到读取器状态(至少在执行下一次写入之前)。使用这种形式的网络共享内存的算法的效率取决于它们在其页面引用中显示读/写位置的程度。李凯(Kai Li)表明,很少同时读写同一数据的多个处理器可以方便地使用这种方法。
Mach提供了一组操作系统原语的定义,这样程序员就可以选择使用共享内存或基于消息的通信作为多线程应用程序实现的基础。根据所需的应用程序样式和可用的多处理器或网络类型,可以根据内存管理原语实现消息传递,也可以根据通信原语实现内存管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值