An Open Operating System for a Single-User Machine

摘要

描述了单用户操作系统的文件系统和模块化。主要的兴趣点是系统的开放性,它在自身和用户程序之间没有明确的界限,以及用来使系统健壮的技术,

1介绍

在过去的几年中,一种关于操作系统的思考方式已经被广泛接受。根据这种观点,操作系统的功能是提供一种子宫(或者,如果你喜欢,一个虚拟机),用户或她的程序可以在其中生存和开发,安全地与外部世界的严酷现实隔离[2,5,13]。事实上,作者之一是这种“封闭”系统[12]的早期倡导者。它们有一些吸引人的特点:

•当硬件太可怕,普通人看不到的时候,隐藏是一种善意,如果不是必要的话。
•有用的和流行的设施可以以统一的方式提供,与实现它们所需的名称绑定和存储分配保持一致。
•系统可以保护自己不受用户的影响,而无需对用户的行为做出任何假设(除了那些隐含在虚拟机定义中)。
•如果所有的底层结构都是隐藏的,可能会提供一个更健壮的设施。

另一方面,如果用户和硬件[4]之间的距离太大,可能会损失很多,特别是当用户需要处理非传统的输入输出设备时。此外,扁平的、全有或全无风格的系统放弃了大量的灵活性,用户扩展或修改系统是极其困难的,因为在两者之间划出了一条尖锐的界线。

在本文中,我们探索了一种不同的、更“开放”的方法:系统被认为提供了各种各样的工具,用户可以拒绝、接受、修改或扩展其中的任何一个。在许多情况下,工具可能成为构建其他工具的组件:例如,文件是由磁盘页构建的。当这种情况发生时,我们会尽可能地让用户能够访问小型组件以及大型组件。这种设计的成功取决于我们在不破坏较大组件的情况下利用小组件的灵活性的程度。特别是,我们必须非常注意系统的健壮性,即从崩溃中恢复和抵抗误用。

我们系统的另一个方面是,文件系统和通信是在低于操作系统中的任何软件的级别上进行标准化的。实际上,标准化的是磁盘上的文件和网络上的数据包的表示。这使得程序可以用完全不同的语言编写(BCPL [4], Mesa [8], Lisp[7]和Smalltalk [10];前者首先出现,并且是本文所描述的软件的主机语言),并使用完全不同的指令集(用可写微码实现)来执行,以共享相同的文件系统和远程设施。在这样做的过程中,它们不会放弃任何存储空间给用外语编写的操作系统,也不会在每次访问磁盘存储或通信时,从一个编程环境和指令集切换到另一个编程环境和指令集的任何周期。

这种灵活性所付出的代价是,对这些表示的任何更改都需要更改几段代码,这些代码是用几种语言编写的,由不同的人维护的;重写的成本如此之高,以至于实际上不可能进行这样的修改。因此,当处理器速度和内存充足时,不推荐这种方法;在这种情况下,最好采用更高层次的标准化。然而,在我们的情况下,该政策使机器的许多主要应用成为可能,否则将完全不可行的。此外,我们发现,这些限制几乎没有造成实际问题,尽管该系统的使用范围远远超出最初的预期。

当然,在多用户系统中,必须有强制性的保护机制,以确保公平和安全地共享硬件资源,这种考虑限制了可以实现的开放。然而,在这些限制范围内,可以做很多事情,并且实际上可以以一种受保护的方式提供下面讨论的工具,而不需要做任何大的更改,尽管本文将其限制在单用户系统中,从而避免了对问题的明确分析。

以这种方式描述整个系统将是一项重大的工作。在这里,我们只讨论磁盘文件系统、进行世界交换的方法以及用包构造系统的方法。

2背景

本文中的示例的操作系统被吸引是写给一个小型计算机称为Alto[16],有16位处理器,64 k 800 ns内存的话,和一个或两个可移动头磁盘驱动器,每个可以存储2.5 mb在一个可移动的包,可以传输64 k字在大约1秒。该机器和系统还可以支持另一个磁盘,其大小和性能约为原来的两倍。该机器没有虚拟内存硬件。处理器执行支持BCPL的指令集,包括过程调用和返回的特殊指令。

这个系统几乎完全是用BCPL编写的,事实上,这种语言被认为是机器编程的标准方法之一。编译器生成普通的机器指令,并且不使用运行时支持例程,除了一小段稍微扩展了指令集的代码。

一次只支持一个用户,磁盘和终端以外的外围设备很少使用。因此,当前版本的系统只有两个进程,其中一个进程将键盘输入字符放入缓冲区,而另一个进程负责所有有趣的工作。键盘过程是中断驱动的,没有关键部分;因此,除了硬件中断系统,没有同步原语和调度程序。因此,系统不控制处理器的分配,实际上只有当用户程序调用某些系统设施时才会获得控制。系统在一定程度上控制存储空间的分配,无论是在主存还是在磁盘上,以使用户的程序能够共存并相互调用。

因此,系统可以被合理地看作是实现各种可能有用的抽象对象的过程的集合。这些系统过程与用户为实现自己的抽象对象而编写的一组过程之间没有明显的区别。事实上,系统代码是作为一组独立的子例程包提供的,每个子例程包实现一个对象,这些包在不需要系统所有服务且无法负担其成本的应用程序中得到了大量的独立使用。

抽象对象有几种类型:输入输出流、文件、存储区域、物理磁盘。所有这些对象都是这样实现的:它们可以是普通变量的值;因为BCPL是一种无类型语言,这意味着每个对象都可以用一个16位的机器字来表示。当然,在很多情况下,这个单词将是一个指向更大的东西的指针。

这些流是从Stoy和Strachey的OS6系统[15]批量复制的,文件系统的许多方面也是如此。为了完整,我们在这里给出一个概要描述。流是一个可以产生或消费项目的对象。项目可以是任意的BCPL对象:字节、单词、向量、其他流等。每个流上都定义了一组标准操作:
从流中获取一个项目;
将一个项目放入流中(通常只定义其中一个);
Reset,将流置于某种标准初始状态(此操作的确切含义取决于流的类型);
输入端测试;

还有一些其他的。这些操作由普通BCPL过程调用调用。
因此,流类似于Simula类[6]。它与类的不同之处在于,实现操作的过程对所有流来说都不相同,而且确实可以不时地改变,甚至对特定的流也是如此。一个流由一个记录(实际上是一个BCPL向量)表示,它的前几个组件包含了提供流标准操作实现的过程。记录的其余部分保存状态信息,这些信息可能因流而异(例如,单词计数、指向缓冲区的指针、磁盘地址或任何合适的信息)。记录的大小不是固定的,而是完全由创建流的过程决定的。

记录也可能包含实现非标准操作的过程(例如,设置缓冲区大小,磁盘文件中的读取位置等)。或者,可以编写任意的过程对特定类型的流执行此类操作。在这两种情况下,过程都接收表示流的记录作为参数,并可以在该记录中存储任何永久状态信息。当然,使用非标准操作的程序牺牲了兼容性,因为它只对执行该操作的流起作用。

这种提供具有多个实现的抽象对象的方案在整个系统中使用。每个抽象对象都是由可以调用它的操作定义的;定义每个操作的语义(或多或少地严格)。可以有任意数量的具体实现,每个实现都为每个抽象操作提供一个具体的过程。层次结构可以这样建立起来。创建具体类型为“磁盘文件流”的流对象的过程需要另外两个对象作为参数:一个磁盘对象,它实现访问文件所在的存储的操作,以及一个zone对象,它用于为流获取和释放工作存储。

3页面和文件

系统将长期存储(在磁盘上)组织成文件,每个文件都是一个固定大小的页面序列;每个页都由单个磁盘扇区表示。尽管文件本身就足够了,但通常需要能够将字符串名称附加到文件上,为此提供了辅助目录功能。由于长期存储的完整性对用户至关重要,因此提供了一个清理过程来从文件系统可能陷入的任何碎片状态重建文件系统的状态。这个过程的需求控制了系统设计的大部分。本节的其余部分将展开刚才给出的大纲。

3.1 页

可用于长期存储的最简单对象是页面。它包括:
一种标签,由以下几部分组成:
F:一个文件标识符——两个字(a);
V:一个版本号-一个单词(a);
PN:页码-一个单词(a);
L:长度(包含数据的页面的字节数)-一个单词(a);NL:下一个链接-一个字(H);
PL:前一个链接——一个字(H);
值- 256个数据字(a)。

组成一个页面的信息有两种:绝对信息(a)和提示信息(H)。页面完全由绝对信息定义。因此,提示的出现只是为了提高实现的效率。每当使用一个提示时,都会对其进行绝对检查,以确认其持续的有效性。此外,还有一个恢复操作,可以从绝对值中重建所有提示。

因此,页面有一个惟一的绝对名称,即文件标识符、版本号和页面号(用(FV, n)表示,其中n是页面号,FV是文件标识符和版本号),它还有一个提示名,即地址。页面的全名(FN)是对(绝对名称、提示名称)。页面(FV, n)的链接是绝对名称为(FV, n-1)和(FV, n+1)的页面的地址,如果没有这样的页面,则为NIL。页面上的基本操作是读取和写入数据,以及读取给出全称的链接。请注意,很容易从页面的全称转到下一页和前一页的全称。

3.2 文件

一个文件是具有绝对名称(FV, 0)、(FV, 1) (FV, n)的页面的集合
(FV, 0)也是文件的名称。文件的基本操作是:
创建一个新的空文件;
在文件末尾添加一个页面;
从结尾删除一个或多个页面;删除整个文件。

因此,如果存在page (FV, n),则0到n之间的所有i都存在page (FV, i)。因此,如果已知文件中某一页的地址,则可以通过链接找到每一页。如果(FV, n)是文件的最后一页,则对于i<n,页面(FV, i)的L=512(即全是数据),最后一页的L<512。

该文件的数据字节包含在第1页到第n页之间。第0页称为leader页,包含了该文件除长度和数据外的所有属性:
创建、最后写入和最后读取的日期(A);
一个叫做leader name的字符串,在章节3.5 (a)中讨论过;最后一页的页码和磁盘地址(H);
一个可能连续的旗(H)。

3.3 代表的页面

磁盘上页面的物理表示称为扇区,由三个扇区组成
部分:
一个头,包含磁盘包号(每个可移动的磁盘包都不同)和磁盘地址;
标签,包含3.1节中规定的七个单词;
一个值,包含256个数据字。

单个磁盘操作可以独立地对每个部分执行读、检查或写操作,但有一个限制,即一旦开始写,它必须在扇区的其余部分继续执行。检查操作将磁盘上的数据与内存中相应的数据逐字比较,如果不匹配,则中止整个操作。但是,如果一个内存字是0,它将被相应的磁盘字替换,因此检查操作是一种简单的模式匹配。

系统使用这些工具使磁盘成为相当健壮的存储介质。磁盘页总是通过其全名访问。扇区的标签总是在写入之前被检查,并且只在三种情况下被写入:

当页面被释放时,必须给出它的全名,并检查标签是否正确。然后将它们写入标签和值中,以确保将页面视为文件一部分的任何尝试都将失败,并出现标签检查错误。

页被分配后的第一次写入—检查该页是否空闲。然后为页面写下合适的标签。

为了改变文件的长度—读取并检查最后一页的标签。然后重写它,可能使用L和NL的新值。

这种方案在每次分配或释放一个页面时都要花费一次磁盘转数,但它使得意外覆盖页面的可能性很小。在任何其他写操作中,标签都被及时检查,不需要任何费用。检查操作与读操作是有区别的,因此,在写任何东西之前,后续的写操作可以中止,而不需要额外的转数。当然,标签也会根据读数进行检查。如果检查成功,可以确定用于访问磁盘页的提示(地址)实际上指向由全名的绝对部分指定的页面。正如我们将在下面看到的,也可以仅从绝对名称找到一个页面(虽然不是很有效),并从绝对名称重构所有的提示名称。

磁盘包含一个称为磁盘描述符的文件,该文件具有标准名称和磁盘地址。它是:
分配图,一个位表,表示哪些页面是空闲的(H);
磁盘的形状,即磁道、表面的数量,以及所需的其他信息
为特定型号的磁盘(a)参数化磁盘例程;
根目录的名称(H)。

注意,分配映射是一个提示,因为关于哪些页面是空闲的绝对信息包含在标签中。如果映射说一个页面是空闲的,分配器在分配它时标记它忙,当上面描述的标签检查失败时,分配器将再次调用以获得另一个页面。因此,地图中标记为空闲的页面会导致额外的一次性磁盘活动。将永远不会分配标记为忙碌的页面;这些丢失的页面将由章节3.5中描述的清除程序恢复。
我们对磁盘描述符的实现与上面的描述略有不同。主目录有一个标准名称和磁盘地址,并指向磁盘描述符文件。出现这种方案是因为磁盘描述符被添加到文件系统数据结构中,因为显然必须以某种方式记录磁盘的形状。上面给出的描述反映了磁盘描述符和主目录之间的逻辑关系(也就是说,这就是我们应该做的)。

3.4目录

到目前为止,我们已经构建了基于页面的数据存储工具和基于文件的分配工具。没有在页级提供分配,因为很容易失去对页的跟踪,而这又因为页的大小是固定的,不能作为逻辑存储单元。另一方面,文件可以是任意大小的,因此是用户将其视为一个单元的数据集合的合适容器(只要它不太小)。因为一个文件是一个逻辑单元,而且,它应该有一个逻辑名称,例如,一个字符串名称,以及它的唯一文件标识符,并且名称应该在某些上下文中解释,这样名称可以独立分配而不用担心冲突。
这是熟悉的推理路线,它导致了树状结构的目录层次结构[5]。我们的系统采用了一种不同的方法(遵循OS6),因为我们希望将文件视为独立的对象。我们认为,只要知道文件的全名(即其第一页的全名),就可以执行对文件的任何操作,并且存在一种单独的机制来将名称与文件关联起来。这是由一个名为目录的文件完成的,它包含一组对(字符串,全名)。一个文件可以出现在任意数量的目录中。因为从文件系统的角度来看,目录没有什么特别之处,所以可以有一个目录树,或者一个任意的有向图。我们确实需要能够识别下面描述的清除过程中的所有目录,为此,我们为目录文件保留了文件标识符的子集。
进一步的暗示(在这里我们与OS6分离)是,必须能够从文件本身恢复某些逻辑名称,这样即使文件的目录条目丢失或被打乱,文件也可以存活。这是领导页中领导名称的目的;它的意义应该从它在清除食物中的作用中可见一斑。在领导页中的信息被认为是绝对的,因为这是一个可以定位文件的名称,即使它的所有目录条目都被销毁。相比之下,目录项就不那么严肃了,尽管它们不是完全多余的,因此不能将其视为纯粹的提示。如果一个目录被破坏了,我们不会丢失任何文件,但是我们确实丢失了一些信息,也就是说,某一组文件被某一组名称从该目录引用。

3.5 扫气

通过读取磁盘上的所有标签,我们可以检查所有链接是否正确(重构任何被证明是错误的链接),获取所有现有文件的全名,并生成一个空闲页面列表。为此,我们所要做的就是创建一个包含所有未标记为free的标签的列表,并按绝对名称对其进行排序。如果有足够的主存储来容纳每个扇区48位的表,那么选择合适的数据结构可以在没有任何辅助存储的情况下完成这个处理。这实际上是机器标准磁盘的情况。较大的磁盘要求将该列表写在磁盘的一个特别保留的部分上。

然后,我们可以读取所有目录,并验证每个条目是否指向现有文件的第0页,在必要时确定地址,并检测哪些条目指向别处。如果任何文件仍未被目录项所解释,我们可以在邮件目录中使用其leader名称为其创建一个新条目。这是leader name的唯一功能。

整个过程称为清理,对于一个2.5兆字节的磁盘,清理大约需要1分钟。当它完成时,所有的提示都会从绝对值中重新计算,并且会检测到任何不一致(不完整的文件、空目录条目、无名文件等)。如何处理不一致的问题超出了本文的范围。清除过程中,任何永久的坏页面都将在标签中标记一个特殊值,以便它们永远不会被再次使用。

正如我们已经注意到的,清除不能完全重建丢失的目录。这可以通过对目录的所有更改写一个日志,并对所有目录偶尔做一个快照来实现。通过将日志中的更改应用到快照,我们将获得当前状态。这当然是一种标准技术,任何数据库的完整性都可以通过这种技术得到保护。由于上述原因,我们不认为我们的目录重要到值得这样的注意。如果用户不同意,他可以自由地修改系统提供的管理目录的过程,或者自己编写。

我们还编写了一个更复杂的清盘程序,它对磁盘上的文件页进行原位排列,以便每个文件的页位于连续扇区中。这种安排通常提高了文件顺序读取的速度,比页面分散时的速度提高了一个数量级。

3.6 使用提示

提示的目的是提高性能。例如,如果一个程序拥有文件页的全名(FV, i)和提示地址,它可以直接访问该页,而不需要进行目录查找,也不需要向下扫描数据块链。如果这个直接访问失败(即,提示地址处的页面不是(FV, i)),程序有几个选项:
它可能对文件的其他部分(通常是领导页)有一个正确的全名。然后,它可以跟踪该页面的链接,仍然避免目录查找。还可以为文件的第k个页面保留提示地址,以减少必须遵循的链接数量。

如果失败,它可能会在目录中查找FV以获得正确的磁盘地址。
如果失败,它可能会在目录中查找文件的字符串名称,以获得新的FV和磁盘地址。
最后,它可能调用清道夫来重建整个文件系统和所有目录,然后重试前面的步骤之一。
注意,这样的提示可以扩展为在文件系统中命名一个特定的字节,只需在页面中增加一个字节位置的完整名称。

对于被认为是连续分配的文件,也可以使用提示机制。程序可以假设一个文件是连续的,并且知道第i页的地址ai,将第j页的地址计算为ai+j-i。标签检查将防止任何不正确的数据覆盖,并将通知程序磁盘访问是否成功。
许多程序使用一组需要快速访问的辅助文件。例如,编辑器使用两个临时文件、一个日志文件、一个消息文件等。当这些程序被“安装”时,它们会创建必要的文件,并将提示存储在数据结构中,然后写入状态文件。随后,程序可以启动,读取状态文件,并以最大磁盘速度访问所有辅助文件。如果提示失败,例如,因为一个临时文件被删除或移动,程序必须重复安装阶段。提示存储在哪里并不重要,系统也不会努力保持它们的更新。它只是确保当提示失败时,不会造成损害,并通知使用提示的程序,以便它可以采取纠正行动。

4.程序之间的通信

大多数操作系统的一个关键目标是促进不同程序之间的通信,这些程序通常用不同的编程语言或环境编写。但是,一个允许程序员拒绝系统所有功能的开放操作系统如何提供通信呢?最保守的解决方案是只允许通过磁盘文件进行通信,因为所有程序都必须遵守文件结构。例如,命令扫描程序可以将用户输入的命令字符串以标准名称写入文件,然后调用执行该命令的程序。普通磁盘文件可以用这种方式将数据从一个程序传递到另一个程序。磁盘文件结构还必须作为一种调用任意程序的方式,也就是说,从一个程序“转移控制”到另一个程序。由于操作系统的开放性,被调用程序和被调用程序可能很少或根本没有共同之处。

通过定义从磁盘文件恢复机器的整个状态的约定来实现这些控制传输;这就允许任意一个程序来控制机器。描述机器状态的文件可以用来实现几个控制规程。协程结构是常用的:程序首先在一个磁盘文件中记录它的状态,然后从第二个文件中恢复机器状态。当机器状态从第一个文件恢复时,原始程序将继续执行。

程序间通信机制有许多用途。例子有:
——引导。硬件引导按钮导致从磁盘文件中恢复计算机的状态,该磁盘文件的第一页保存在磁盘上的固定位置。这个启动文件可以由一个向文件中写入程序和数据的链接器来写,这样当机器状态从文件中恢复时,这些程序和数据就会构成一个正在运行的程序。或者,文件可以通过保存运行程序的状态来写入,每次机器启动时都将恢复运行程序的状态。
——调试。当遇到断点或用户敲击键盘上的特殊DEBUG键时,机器的状态被写入磁盘文件,并且从包含调试器的文件中恢复机器状态。调试程序可以通过读取或写入作为断点结果写入的文件的部分来检查或更改有故障的程序的状态。稍后,调试器可以通过从文件中恢复机器状态来恢复原始程序的执行。因此,原始程序和调试器作为协同程序运行。
——检查点。程序偶尔会将其状态保存在磁盘文件中。然后它可能会被中断,要么是处理器故障,要么是用户动作(例如,引导机器)。稍后可以通过从检查点文件恢复机器状态来恢复计算。
——活动切换。协程结构用于在多个任务之间切换,这些任务是单个应用程序的一部分。一个例子是打印服务器,这是一个从本地通信网络接收文件并打印它们的程序。该程序分为两个任务:一个假脱机程序,从网络中读取文件,并将它们放入磁盘文件的队列中;一个打印机,从队列中删除条目,并控制打印这些条目的硬件。因为每个任务都有相当大的内部状态,并且在不同的环境中操作,所以它们使用状态保存/恢复机制进行通信。当后台处理程序空闲但队列不为空时,它保存状态并调用打印机。无论打印机何时完成或检测到传入的网络流量,它都会停止打印机硬件,保存其状态,并调用假脱机程序。这个方案可以很容易地中断打印,以便快速响应传入的文件。

在许多系统中,状态恢复机制非常危险,因为它们可能导致磁盘文件结构严重损坏。这可能发生,如果一个程序在内存中保存当它包含本地区的磁盘数据结构(例如,一个目录,或分配地图表明自由块),从来没有恢复,或未能更新这些信息来反映实际磁盘状态后恢复。第3.3节中描述的标签检查机制可以防止信息更新不正确时造成的灾难性损害。此外,保存和恢复的提示通常仍然有效,可以用来快速重新读取缓存在主内存中的任何磁盘数据。

4.1 InLoad和OutLoad

InLoad和OutLoad两个过程是最常用来操作包含机器状态的磁盘文件的过程。每个例程都接受一个磁盘文件的全名作为参数,并且需要大约一秒钟来完成它的操作:

(written, message) : = OutLoad(OutFN) InLoad(InFN, message)

OutLoad将当前机器状态写入文件,并以写入标志true返回。注意,保存在输出文件上的程序计数器在OutLoad过程本身中。InLoad过程从给定的文件恢复机器的状态,并向恢复的程序传递一条消息(大约20个单词)。结果是OutLoad再次返回,这次返回的是编写的false和InLoad调用中提供的消息。协程链接的代码如下:

messageToPartner = parameters to pass in coroutine call; (written, messageFromPartner) := OutLoad(myStateFN);
if written then InLoad(partnerStateFN, messageToPartner); messageFromPartner contains parameters passed to me;

如果协程调用中的参数不适合小消息向量,则使用该向量传递磁盘上写入参数的位置的全名。消息通常包含一个返回地址,即在返回时要恢复的文件的全名。在上面的例子中,可以通过在InLoad调用之前将myStateFN复制到messagetpartner中来提供返回地址。
InLoad和OutLoad过程虽然非常小(大约900个字),但仍然会被足够错误的程序所消除。对于连接到调试器,如果以某种方式保护这些例程,将是更可取的。没有内存保护硬件的机器可能应该在只读存储器(或处理器微码,不会被损坏)中实现程序。我们通过一个特殊的紧急引导程序来解决这个问题,该程序只包含OutLoad过程,该过程将机器的大部分状态写入磁盘文件。不幸的是,这种方法不能保存一些最重要的状态(例如,处理器寄存器)。

5.开放系统的组织

操作系统是一组常用的子程序包的集合,它们通常存在于内存中,以方便用户程序。系统提供磁盘文件、键盘输入和显示输出的流;直接读写磁盘页的例程;OutLoad和InLoad程序;一个自由的存储分配器;BCPL运行时例程;存储大量方便的数据,如常用文件的提示、用户名和密码等。子例程包几乎完全用BCPL编写,对于存储分配和对象调用具有一致的约定。

系统包括一个调用在操作系统下执行的BCPL程序的过程。程序的代码从磁盘流中读取并加载到低内存地址中。使用代码文件中包含的修复表绑定所有对操作系统过程的引用。最后,通过调用一个单条目例程来调用程序。程序可以通过调用程序加载器读入另一个程序从而覆盖第一个程序来终止,也可以通过从主过程返回来终止。如果程序返回,系统加载并运行一个标准的执行程序。执行程序从键盘接受用户命令并执行它们,通常通过调用加载程序来调用用户请求的程序。

在操作系统下运行的程序也可以从一个完全不同的编程环境中调用。在包含操作系统状态的文件上调用InLoad过程,这将导致加载和初始化系统。传递给InLoad的消息向量可能包含一个文件的名称,该文件包含要调用的程序。在这个文件上打开一个流,程序被加载并运行。

5.2 junta

构成操作系统的包被组织起来以支持其开放性。不愿使用系统提供的标准过程的程序,或者需要使用标准过程所占用的内存空间的程序,可以请求从内存中删除部分或全部系统过程。删除程序的程序被称为军政府,因为它强行接管了机器。当程序终止时,将调用counter军政府过程从操作系统的InLoad/OutLoad上下文中恢复标准过程。
系统被组织成几个层次的服务,因此一个程序可以选择它希望保留的程序。过程的排列使最低层(包含最常用的服务)位于内存的最顶层。不太普遍的服务处于数字较高、内存较低的级别。将保留的最高级别数字作为参数传递给军政府,它删除所有更高级别的数字,并释放它们占用的存储空间。counter军政府过程恢复所有被删除的级别,并重新初始化它们包含的任何数据结构。

每一层的设施概述如下:
1.OutLoad / InLoad CounterJunta
2. 键盘输入缓冲区。
3.重要文件的提示。
4. BCPL运行时过程(例如,堆栈帧分配器)。
5.磁盘(标准磁盘的磁盘对象的代码和数据)。
6. Zones(标准自由存储对象的代码)。
7. 磁盘流(标准磁盘流对象的代码)。
8. 磁盘目录。
9. 键盘流(标准键盘流对象的代码)。
10. 显示流(标准显示流对象的代码)。
11. 程序加载器和军政府程序。
12. 系统免费存储,包括默认显示流、磁盘流等空间。

键盘输入缓冲区几乎总是存在,因此用户在运行一个程序时提前输入的任何字符都会被保存下来,以备下一个程序解释。

军政府和counter军政府程序让程序员简单而精确地控制保留在内存中的操作系统设施。与交换代码段等更复杂的机制不同,该方案保证驻留系统的性能。
用户的过程和数据与系统的过程和数据没有区别。例如,存储分配器将构建zone对象来分配内存的任何部分,不管它是否在系统空闲的存储区域中。创建磁盘流对象的例程需要另外两个对象作为参数:一个为流数据结构分配空间的区域(默认为系统空闲存储区域),一个用于调用磁盘传输的磁盘对象(默认为“标准磁盘”)。使用大型非标准磁盘的程序通常包含一个包,该包仅为特殊磁盘硬件实现磁盘对象,并使用标准操作系统磁盘流实现打开文件流。
希望获得更大灵活性的程序员可以使用军政府删除系统的大部分内容,并将标准包的副本合并到自己的程序中,放在任何他想要的地方。使用这种方法的一个常见原因是,由于内存空间不足,程序员不得不覆盖程序结构。例如,一个文件服务器程序只使用非标准的大磁盘,但使用标准的磁盘流包,组织在覆盖。显示器、键盘和存储分配包已经组装成一个操作系统,无需磁盘即可使用,用于支持诊断或其他依赖网络通信而不是本地磁盘存储的程序。
作为一组子例程包的操作系统能否成功,主要取决于包的设计。将常用过程保留在内存中可以减少许多程序的大小,从而节省磁盘空间。在内存中保留通用数据结构可以节省初始化时间。军政府的程序是方便的,但不是必须的。在改进子例程包方面花费了相当大的精力,这使得子例程包既可以用作内聚的操作系统,也可以用作独立的包。像任何语言设计一样,这是一项非同小可的任务,其难度被结果的简单所掩盖,

6.结论

我们描述了一个小型操作系统的三个主要部分的设计。在每一种情况下,都花费了相当大的精力让用户能够访问所有的工具,在某种意义上说,如果系统提供的原语不令人满意,用户可以从系统中的原语建立自己的宏操作。在处理文件时,我们强调了将数据被破坏的可能性降到最低的方法。并且允许在崩溃后完全自动恢复。程序通信设施强调控制整个机器并以不同方式组织它的程序之间的合理通信。层次的组织容纳的程序并没有走得太远,但仍然需要对自己的命运有很大的控制;在这里,对组成系统的软件包进行适当的设计,以允许独立操作是至关重要的。
为使文件系统健壮而采取的措施(其中标签检查至关重要)已经非常有效。目前存在数千个文件系统,运行在数百台机器上,没有任何集中维护。关于信息丢失的投诉发生率是微不足道的。提示方案也能很好地从系统中获得高性能。然而,由于对提示的正确使用的解释不足,许多程序员不能确切地理解什么是提示,什么是绝对的,或者如何从提示的失败中正确地恢复。因此,程序崩溃并提示“提示失败,请重新安装”的情况比正常情况更常见,而不是自动调用适当的恢复过程。
该系统的开放特性也很成功,并培养了大量不同的编程环境,它们非常和谐地一起工作。军政府经常被用来删除模拟电传打字终端的人工输入/输出的标准处理程序,因此实验程序可以非常小心地或以新颖的方式控制交互。
开放的缺点在于人们的预期。因为虚拟化系统是不可能的,所以没有实际的方法来更改文件系统或通信的表示或功能。此外,无法拦截对文件系统、显示或其他内容的所有访问,并将其指向其他设备,例如远程文件系统。这只能通过改变机器的微码来实现。

An Open Operating System for a Single-User Machine翻译相关推荐

  1. C/C++ tip: How to detect the operating system type using compiler predefined macros

    转自:http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_oper ...

  2. 一些关于ROS的讨论 Robot Operating System – A flexible framework for writing robot software (ros.org)

    https://news.ycombinator.com/item?id=17916456 Robot Operating System – A flexible framework for writ ...

  3. CPT104 Operating System Concepts Note

    Word 直接复制过来标号有错误 Lecture 1 Process What is an Operating System? OS An Operating system is the heart ...

  4. 《modern operating system》 chapter 3 MEMORY MANAGEMENT 笔记

    MEMORY MANAGEMENT The part of the operating system that manages (part of) the memory hierarchy is ca ...

  5. xv6: a simple, Unix-like teaching operating system|Chapter 1 Operating system interfaces

    Chapter 1 Operating system interfaces 1.0 Overview ❓ Recall The job of an operating system How does ...

  6. How to Make a Computer Operating System

    How to Make a Computer Operating System 如何制作一个操作系统(翻译版) 原文地址:Github:How to Make a Computer Operating ...

  7. VMware vSphere Client中启动虚拟机提示No boot filename received/Operating System not found解决方法

    VMware vSphere Client中启动虚拟机提示No boot filename received/Operating System not found解决方法 参考文章: (1)VMwar ...

  8. vm虚拟机安装系统后出现operating system not found解决办法(VM装ghost 不能进系统的解决方法)

    vm虚拟机安装系统后出现operating system not found解决办法不知你使用那种软件分的区?   用DIANGEN的话,它本来就清楚列明了激活分区选项的. 如果用PQ分区的话,还必须 ...

  9. Directory lookup for the file xxx.mdf failed with the operating system error 2

    Directory lookup for the file "xxx.mdf" failed with the operating system error 2(系统找不到指定的文 ...

  10. 成功解决解决VM软件安装Linux的Ubuntu过程,打开时 Operating System not found

    成功解决解决VM软件安装Linux的Ubuntu过程,打开时 Operating System not found 目录 解决问题 解决思路 解决方法 解决问题 安装Ubuntu16.04虚拟机,打开 ...

最新文章

  1. python spark 求解最大 最小 平均
  2. 清除右键菜单CMD入口
  3. mkswap,swapon, swapoff命令:创建交换分区
  4. java 并发测试main方法_Java并发测试
  5. Vue Vuex的详细教程
  6. 凯兑换系统服务器角色,能够在所有局中通用的角色,游走于各个线路,单挑很强的凯...
  7. [Git]4.1 分支与合并
  8. opencv sobel算子的理解
  9. 《时空幻境》Braid.v1.010.r2-RES-patch
  10. BT没死!305个国外BT资源聚合站点大全
  11. 计算机查找的快捷键是,电脑快捷键快速查找
  12. 【C语言】(用函数实现)任意给定两个正整数a和n,计算a+aa+aaa+aa...(n个a)的和。(例如输入1,3即为计算1+11+111的值)。
  13. C++分数类(类与构造)
  14. 巴比特《8问》专访 Conflux 创始人龙凡教授
  15. 渲染算法学习(四)-- Environment Lighting
  16. 运筹说 第5期 | 运筹学江湖的形成
  17. Mac安装brew(2020年踩过无数坑后亲测有效的方法)
  18. css改变纯色图片颜色的几种方式
  19. Win32-子窗口-父窗口-窗口所有者
  20. ckeditor5 vue 字体大小配置,字体颜色,段落对齐API设置

热门文章

  1. NB-IoT芯片战即将爆发,华为和高通谁会获胜?
  2. python检测键盘按键命令_python实时检测键盘输入函数的示例
  3. 【涨薪规律,四个词:英语、外企、进修、跳槽。】---留作参考
  4. 关于strcmp与strcpy函数的相关用法
  5. 邹健写的公交车路线查询(包括转车近到远排列)。
  6. 我做的邹健老师的sql练习题(含答案)
  7. 7-2 地下迷宫探索 (30分)
  8. 使用curl进行网站测速
  9. 百度高德地图 坐标系转换
  10. 中兴通讯云网解决方案介绍