重点单词和短语: 协作的进程,操作系统、 信号量、 信号量的应用程序、信号量队列、 死锁、 deadly embrace、 分层结构、 多道程序设计,操作系统结构、 异步结构、 缓冲、并行进程、同步原语、可重入代码、RC 4000 、 时间安排、调试、 项目规划、 调度、 可靠性、 程序证明、 协同程序、 正确性、程序维护,软件分页。
1.介绍
1.1BOSS 2的设备
BOSS 2 操作系统是RC 4000在1970年到1972年的进化。Boss 2 是一个以通用为目标的操作系统,并同时提供以下服务类型: 批处理作业、 远程作业入口、 时间共享 (会话作业)、 由其他作业内部生成的作业和进程控制作业。该操作系统可以是计算机网络的一部分的同时,允许作业传输文件到CDC 6400和 Univac 1106/1108。
BOSS 2拥有最大50个终端,多种类型的辅助存储器和磁带、打印机、读卡器、 打孔机、 绘图仪和各种进程控制设备。资源可用于所有类型的服务。BOSS 有一个基于交换和更新的一个考虑到所有任务的资源需求的作业完成时间估算的动态优先级系统。这一估计数来自有效的终端。所有的设备通过32K字节的核心存储和磁盘的2M字节存储都是可用的。
在一个配置了20个终端机,64K字节的核心存储器和一个额外的小磁鼓(drum)的 服务中心进行性能测试。任务是储存媒介和大量数据处理程序的运行和调试。在最繁忙的6个小时里,CPU的使用率有40%-50%是被作业占用,10%-20%是由操作系统和处理显示器占用。平均每个作业的操作系统开销是3秒--包括操作系统中不重复输入输出的转换。对于简单的在线命令例如编辑命令(小于0.5秒)的响应时间是忽略不计的。在第一年运作,期间系统通常跑几个星期没有崩溃。现在,这似乎是不定时的出错。
1.2 不用Boss 2 的 RC 4000
(实在是来不及了,挑着翻译吧)
Monitor(内核?)是一个让计算机好像在同时执行多个程序(programs)的程序(procedures)集合。一些程序是嵌入驱动程序(额外进程),一些程序是执行一个用户定义的程序(作业步骤)的任务进程,一些程序是操作系统。
任意两个进程能通过信息进行通信和同步。每个进程在保护的Monitor中有消息缓冲区集合,它有一个可以接收来自其他进程的缓冲消息的消息队列。它可以唤一个Monitor进程等待请求直到一个缓冲消息在这个队列中,它也可以返回一个队列缓冲给发送方。两个另外的Monitor进程允许它发送一个消息给其他进程并等待收到回复。一个更进一步的Monitor进程--本质上是为了操作系统的实现--允许一个进程等待第一个消息(或者回复)的到来。
一个进程拥有像工作内存和消息缓冲区的资源集合。它可以使用这些资源中的部分来创建另一个与创建者(parent)并行运行的子进程(child)。之后父进程可以移除子进程并把资源回收。一个操作系统类型进程就是通过这种方式创建作业进程。
实际用来任务和操作系统以及任务和驱动器之间通信的规则是在1969年到1970年研究出的。那意味着,在任何先进的操作系统之前就计划了。在这个早期大量 的编译器和实用程序已经被开发了,因此为了兼容性问题BOSS系统必须遵循以小额旧的语用规则。
在1969-1972年期间,计算机大部分操作都是通过一个非常简单的只处理核心内存任务进程的操作系统来操作。当有新的或者要删除任务进程通常是手工调整执行顺序并且立即执行或者被拒绝执行。一个任务进程会发送两种信息:1输入输入出信息给驱动器2 parent 信息给操作系统。输入输出消息询问操作是非常接近硬件的,比如转移一个数据块或者把磁盘放到合适的位置。输入输出策略和出错恢复大多数是用户程序和库过程(library procedures)处理的。parent消息请求各种函数,比如挂载一个磁带,挂载一个纸带,终止作业,使作业在最多x秒内停止,输出一个操作消息等。
这个简单的操作系统简单地在控制台输出所有父消息,并不需要去理解这些消息。虽然通过这种方式处理磁带加载和卡纸是非常方便的,但这方法并不适用于处理磁盘上的文件处理(打开文件、创建文件等)。早期系统设计的一个主要失败在于文件处理并不是作为父消息进行通信的--在简单的操作系统中自动处理。取而代之的是一组特殊的监控程序(Monitor)集合的提出,它甚至没有使用消息机制。其结果是,更高版本操作系统不能“catch”到文件处理请求,而且磁盘分配策略因为Monitor而变得受限制。
1.3The Plcae of Boss 2 in RC 4000
这些是我们在开始发展Boss 2的时候的条件。我们不能改变已存在的软件除非是完全需要的。然而,我们很快发现俺去定义和扩展Monitor里的文件处理进程是很有必要的,而且这个工程在Boss 2中并行的被同时开发了出来。
图2展示了执行Boss 2 程序的Boss进程。作业进程是Boss的子进程。Boss从作业进程接受消息,并请求操作完成时发送回复。当然作业发送所有的父消息给Boss,但有些输入输出消息也发送给Boss,因为Boss模拟一些设备并对作业来说像是一些设备集。设备模拟非常慢,设备需要spooling假脱机技术,并且设备很难实现共享(终端的速度较低,纸读卡器,打印机)。作业直接发送输入输出消息给快速设备比如磁盘,磁带的驱动器。
Boss发送消息给各种驱动器或者去完成设备模拟(终端、读入设备、输出器)或者去执行一个父消息(读一个磁带标签来和父进程联系“装载磁带”)。
在Boss中,一些并行活动区的集是同时进行的:一个activity与每个作业同步并且一个与每个外围设备同步。这些activities在原则上会与其他的之间通信,如图2中所示。每一个activity能被作为一个进程在monitor下执行,但是子啊一个不成功的项目(Boss 1)我们学习到了进程和消息为了此目的完全不适合。
主要的问题在于每个进程有他自己的消息队列。例如让一个消息队列代表一个空闲记录池是不可能的因为只有一个进程能从队列中获得消息。同样由于这个原因,Dijkstra的为重要寄存器构建的信号也不能被直接消息生成。通过介绍一个管理员进程的方法解决这些问题是可能的,但这样的逻辑会变的复杂的。
另外RC 4000进程重新载入是非常困难的,而且他们不是容易分享的代码或者数据表,尤其是正在发生交换或者分页的时候。
最终,只有23个附加进程驱动可以在RC 4000被创建,我们需要超过一百个并行activities包括Boss。所以在所有的情况下,我们不得不在一个进程内模拟更多的并行activities。
我们选择的解决办法是另一级别的多进程运行在单Boos进程内运行。
这种"多道程序设计系统"的monitor(内核)被称为Boss 2 中央逻辑,并行的activities(作业?)被叫做coroutines(协同程序),通信和同步是通过简单信号量和信号量队列的方法来解决的(下文有述)。协同程序运行模拟在一个通过中心逻辑模拟的虚拟内存中,并且核心存储区域的工作进程被视为特殊的页面。对周围的环境(在传统的多道程序设计系统中更换中断)同步内核的“wait event”过程处理的方法来处理的,“wait event”允许中央逻辑等待的第一应答或消息(第一个"中断")。
下面我们将讨论协同程序并说明在理想化图片2中到实际的图3中死锁问题的改变。
这种设计被证明是由平行活动管理的 (一个与每个作业同步和一个与每个外围设备同步)。为了防止死锁事后强加了一种并行作业的分层结构。
2.协同程序和信号量。
2.1基本的协同程序方案
每个Boss的协同程序会通过一个快速判决的外围设备或者一个工作进程来执行一个作业。下面一些代表性的activities将会被同时地执行。
a.从磁盘到行式打印机快速的输出数据,尽可能
b.从读卡器读取数据到磁盘
c.与用户终端编辑操作等通信
d.与第二个用户终端通信
e.执行一个用户进程,如处理来自工作进程给Boss发送的消息
f.执行第二个用户的工作进程。
这些协同程序被认为是并行的程序,唯一的本质区别是严格的调度cpu时间。
协同程序只使用少数的cpu时间和磁盘占用时间,因此他们并不需要造成彼此延迟。
通常使用以下算法执行协同程序的基本策略
Step1,等待请求
Step2,发送限定数量的请求给其他协同程序或者驱动器
Step3,应答步骤1中的请求
Step4,发送限定数量的请求给其他协同程序或者驱动器
Step5,跳转到步骤1
不同协作程序算法的代码大小不一,“rewinder”只有30个指令,而“执行用户作业”和“用户终端通信”将打到几千行指令。
2.2信号量队列
在协同程序中通信和同步是通过队列信号量和简单的信号量。一个“queue semaphore ”(队列信号量?)是一个代表记录队列或者协同程序等待被放入队列的记录的集合。
中央逻辑的两个程序负责处理队列信号量:
waitq(semaphore, record)
sigq(semaphore, record): 嵌入了由pointer指定的record,若协同程序等待的record在这个队列中,这其中的一个将被激活,然后随后将运行。
队列信号量和消息的主要区别是一个队列信号量不属于某一个单个进程或程序。另一个区别是records可以是任意长度的,而消息缓存是严格的8字的节倍数。
当协同程序内部通信,两个信号量都被涉及的。一个信号量保存请求,另一个保存应答。
2.3 Simple Semaphores(简单信号量)
Simple Semaphores是由Dijkstra提出的。它跟队列信号量类似,但队列没有明确的表现。只有一些records在抽象“queue”是有迹可循的。
因此,简单信号量当records在用户定义的方式相联系时或者record没有包含重要的信息时被执行队列。
Simple semaphores被中央逻辑的下面两个程序执行
wait(semaphore)
sig(semaphore)
2.4 Critical Regions(临界区)
一个临界区是一部分更新一些进程或者协同程序共有变量的代码段。如果在共同变量维持着一个确定的关系,一个进程必须在其他进程进入临界区操作这些变量前完成临界区操作。
一个良好的解决方法是使用一个带有包含共同变量的记录的队列。
2.5 Private Buffers and Messages(私有缓冲区和消息)
多缓冲通信一个特殊情况是频繁地使用。每个发件人的请求有他自己的记录,他想要的回复可以通过他私有的信号被
返回,则可能很简单。私有信号量在请求中是指定的。发件人以这种方式使用的基本方案。
3.1不会发生死锁的基本证明
我们可以证明不会发生死锁通过没有协同程序在有效工作去做的时候不会一直等待。
作为一个更重要的例子考虑协同分配给作业的资源的"银行家"。当一个协同程序想要保留或释放资源,它将发送一个私有的缓冲区 (第 2.5 节) 发送到银行家指出相关的资源。它马上获取请求的回复以及当有足够的可用资源的请求预留资源的回复。再次,银行家可以跳过第 3 步中的应答,直到更多资源已被释放。在这种情况下是证明有点复杂,假定最大值一份工作所需的资源集是在作业开始的声明。分配算法和这个证明的细节在[11]相关文献中查阅。
3.2Hierarchical Structuring and Coroutine Structuring(层次结构和协同程序的构建)
4. Implementation Principles (实现原理)
4.1 Virtual Store(虚拟存储)
协同算法所占用的总空间、记录和其他变量对于核心存储来说太大了。相反,我们实现了一个基于软件分页的虚拟存储方式。
虚拟存储中的每个字节都由22位的虚拟地址构成。低位的地址范围对应的虚拟存储的内存驻留部分 — — 通过虚拟地址映射到硬件的核心地址。虚拟地址的中间部分对应于虚拟存储磁鼓--当要求时被转移到核心存储的部分。高位地址也是是相似的但对应于磁盘上的虚拟存储部件。虚拟存储按节,在那里每个节是在设备上的物理块的完整数目(块大小等于256个24位的字节)。每当虚拟存储字被需要,并不在核心存储中,包含这个词的整个节都要转移。在实践中,我们认为虚拟存储按照连续的单词划分为页。页面通常被分配在某节中以允许整个页面在页面访问初始化后能快速寻址。几个小页分配在一个块部分而大页面占据整个节。
4.2 Coroutines(协同程序)
每个协同程序由居于核心存储的8字节的协同描述表示。一个字节用来作为一个链接,或者到一个信号量(当协程等待它),到页面调度队列(当协程程序等待页面调入),就绪队列 (当它等待 cpu 时间),或应答队列 (当它等待一个驱动程序的回复)。一个字节用来确定驱动器应答等待,或在有关队列信号量操作期间的工作。五个字包含虚拟地址,代表页面将举行核心店同时协同使用 cpu。有点在每一个这些页面说明单词显示这样它应该写回是否由协同修改页。第一页描述总是表示在其中的代码页发现了当前的协同算法。最后一位页描述表示例程的返回地址。该地址是相对于代码页的开头。
4.3 Semaphores(信号量)
每个信号量是由 3 个内存字节表示。一个字是记录数目的计数或— — 当为负数 — — 等待的协同程序数目。两个字节指向记录队列的开头和结尾(或协同程序队列的等待信号量描述)。这个信号量表示相当麻烦,也可能被替换中所示的一个字节表示形式。队列的记录是虚拟存储中的页面— — 通过他们的第一个字节链接在一起。
4.4 分页方法
如上文所述,使用按需分页。特别有趣的的是事实上可能几个页面同时请求换页,而且任何页面大小 (具体的节的大小)可能被用到。内存中的页面协同传输页从其他协同程序的请求。它将完成对于一个协同程序的所有请求,在它处理之前在它的请求队列中的下一个协同前完成。它等待磁盘和磁鼓传输作为所有其他协程通过进入中央的逻辑的方法,从而允许执行的其他协同与他们所有页中的当前页面在核心存储中。页面协同程序和中央逻辑保持核心存储区中的每个页面的的一个优先级。优先级表示一个最近最少使用的策略,但关于到目前用作 I/O 缓冲区或工作流程的页面。后一种类型的页面将有一个非常高的优先级别直到应答到达或通过银行家算法交换了工作过程。页面尝试用一个简单的策略在低优先级的核心存储部分分配页面。
5. Project Plan and Time Schedule(项目计划和时间安排)
Boss 2的设计是在 哥本哈根的Regnecentralen开始的,在 1970 年 8 月由 Klavs Landberg, PerMondrup和作者。1970 年 10 月,我们完成了项目规范作为一份内部报告。报告指定的设施的这一部分第一个版本,可能日后的扩展出版于 1971 年 3 月 [13]。在本节中,我将给摘要项目规范和解释关键的估计。在 5.4 节,我将该项目的实际进度比较。
项目规范了密密麻麻的写了25页。这些设施是如下所述。为每个外围设备类型都有使用者在Boos系统中用于处理它以及操作者使用的方法。
设备被认为是:类似打字机的终端、 纸带读入器、 打印机、几种类型的磁带,几种的磁鼓和磁盘。在线的命令,执行,和概述了在线编辑器的约定。还介绍了在备份存储区,资源分配作业调度和交换策略,用户目录、 帐户和统计数据的文件。一部分估计存储需求和总的系统开销。一个十页的的部分描述了基本的项目决定实施前的21种主要的扩展方法。
共有四人 被视为执行小组与基于检查点的时间安排
如下:
1970 年 11 月。关于扩展的最后决定。
1970 年 12 月。内部详细的规格
结构和所有的并行活动之间的接口
里面的老板。
1971 年 2 月。调试的核心逻辑。所有其他部件大力推进。
1971 年 5 月。样机调试。
1971 年 7 月。样机完成安装。
后来的事实证明,原型是1972 年 4 月完成,第一次公开发布1972 年 8 月,这一时间表似乎完全都是荒谬。
然而,让我们看到,我们如何到达它。
关键的一点是指令的总数量估计。我们的是基于设备列表和策略——不是糟糕的——我们估计等同于我们 algol 语言编译器。
一开始估计,Boss有7000条指令。
5.2 Planning a Debug Session
5.3 Choice of Programming Language, Paging
作者以前曾参与在RC 4000 上通过Algol 5开发的Boss 1。虽然Algol 5实现此目标是足够的,但是用Algol来表示协同程序的重载是非常累赘的。更糟的是,然而,是面向对象代码要长于相当于4至5倍原来手写的汇编语言代码。具有相同换页开销需要 4 至 5 倍更多的核心存储。
应该指出的是,Algol5 编译器生成相当好的代码。举个例子说,Algol W在mr~360 生成非常高效的代码,但调查表明它跟Algol 5 代码一样长。
基于Boss 2的禁止长对象编码的目标,获选的是汇编语言。
RC 4000 有没有用于分页的硬件,所以必须要引入软件换页。
在 1972 年 1 月,我们最后检测到延迟的真正原因。我们编制了 20,000 指令而不是估计的 7,000。当项目进入
1972 年 8 月的维护阶段,我们编制了 26,000个指令(包括一些进一步的扩展)。
5.5 总结
估计错误的主要原因是指令的数量被低估了三倍。用一个当时非常先进的表技术来估计代码长度,但类似的技术没有被运用到Boss 2中。
低估了的第二个原因是Monitor(内核接口)。Monitor在期间被Boss所需的设备接口扩展了。
6.评价
6.1 性能
正如最初规定的设施有时扩展的版本中实现。我们放弃一个扩展--vdu终端--因为硬件未被开发。另一种扩展--打印机备份磁带--上没有已投入操作,部分因为似乎没有非常的需要它。
辅助存储器和核心存储很好的符合了规范。然而,有些低估了系统开销。当Boss在指定的核心区 (15,000 个字符)运行,开销会多次超过估计,因为存在系统颠簸。当Boss使用在核心存储使用30,000 个字符,开销是估计的1.5倍 (实际上 3 秒开销要执行的作业)。
6.2 可靠性,Bug,证明
当我们开始Boss 2 的设计时,我们知道RC 4000 软件是非常可靠的。在大学环境中,该系统通常跑下简单操作系统三个月不崩溃。虽然编译器中存在的一些错误和实用程序,它们最多影响一个工作进程。目前的崩溃可能是瞬态的硬件出现错误。外围设备中的错误更频繁出现,但不破坏系统的其余部分。
一开始,我们的目的是在Boss实施后六个月相对的稳定。所以我们并没有实现任何重启设施,只是磁盘上的永久文件被保存由一个简单的策略。我们相信这个决定是一个主要原因相对简单而又稳定的操作系统。
事实上,老板 2在开始运行后,通过了在 1972 年 9 月的一个3周的交付测试。