THE SOLO OPERATING SYSTEM: A CONCURRENT PASCAL PROGRAM 譯文

鄭德倫 中科大軟件學院 原創內容轉載請註明出處
這是使用Concurrent Pascal語言寫的單用戶操作系統solo系統的一個描述。它支持順序和併發(Sequential and Concurrent)的Pascal語言爲PDP 11/45計算機開發。輸入/輸出被併發的進程處理,Psscal程序可以相互之間遞歸的調用,並且通過他們傳遞任意的參數。這讓使用Pascal作爲一個作業控制的語言變成可能。Solo是第一個分層的併發程序的主要實現,對抽象數據類型(類,監視器和進程)編譯時控制的最訪問權限。他以用戶的觀點描述,就像介紹另一篇論文一樣介紹自己的內部的結構。

INTRODUCTION:

這是第一個用Concurrent Pascal編程語言寫的操作系統Solo操作系統的描述。這是一個簡單但是很有用的單用戶操作系統,用於PDP 11/45計算機開發和發佈Pascal程序,在1975年5月開始使用。
以用戶的觀點,系統並沒有什麼不同的地方。都支持編輯,編譯,存儲,順序和併發的Pascal程序。這些程序可以使用不同級別訪問任何一個控制檯,卡帶,打印機,磁帶,或者磁盤(逐字符,逐頁,逐文件,或者通過直接存取設備)。輸入,處理,文件的輸出被併發的進程控制。Pascal程序可以遞歸的調用另一個並且通過這個傳遞參數。這讓使用Pascal作爲一個作業控制的語言變成可能(Brinch Hansen 1976a)
對系統程序員來說,Solo系統與其他操作系統有非常大的不同:
1、 少於4%的部分是使用機器語言寫的,剩餘的部分使用順序和併發的Pascal語言
2、 與面向機器的語言不同,Pascal不包含低級程序設計的特性,像是寄存器,地址和中端。這些都是通過被編譯的程序運行時,虛擬機來處理。
3、 系統保護大部分是通過編譯時期檢查訪問權限來實現。運行時的檢查只佔很少一部分,並且這不被硬件機制支持
4、 Solo系統是通過抽象數據結(類,監視器,進程)構來實現的分層程序設計的第一個主要例子。
5、 完整的系統包含大於10萬多字的機器碼(包括兩個編譯器),整個系統由我和一個學生在不到一年的時間開發。
去欣賞Concurrent Pascal的用處,需要充分理解至少一個由這種語言實現的操作系統。本描述的目的就是在學習solo 操作系統內部結構之前,以一個用戶的觀點來看一下Solo操作系統。(Brinch Hansen 1976b)。他介紹了用戶在這個系統上怎麼操作,他內部的數據流是什麼,程序如何彼此調用和傳遞信息,文件是如何存放到磁盤上的,以及在典型任務上面系統執行的如何優秀。
作業控制:
用戶通過顯示器控制程序的執行(或者通過電傳打字機)。用戶通過寫出一個程序的名字和參數來調用程序,例如:

move(5)
read(maketemp, seqcode, true)

第一行命令地位一個磁帶到文件號爲5的地方,第二行輸入到磁盤文件並且並將其保存爲名爲maketemp的順序代碼。布爾類型的true保護了文件在以後不會意外的刪除。
當用戶需要幫助的時候,程序試圖變得有幫助。如果用戶忘記了那個程序是有用的,他可以輸入命令

help

或者其他的命令。系統會迴應:

not executable, try
list(catalog, seqcode, console)

(不是可執行文件,嘗試列出 目錄,序列碼,控制檯)
建議的命令在控制檯列出了所有連續的程序的名字。
如果用戶確定知道磁盤包含了一個程序,但是不確定參數傳遞,他可以簡單的使用程序名調用程序,而不使用參數例如:

read

這個程序就會給出必要的信息:

try again
read(file: identifier; kind: filekind; protect: boolean)
using
filekind = (scratch, ascii, seqcode, concode)

通過讀取一個程序的手冊可以獲得更多的信息:

copy(readman, console)

一個用戶會話可以由一個新的Pascal程序從卡帶到磁盤的輸入開始

copy(cards, sorttext)

接下來是編譯:

pascal(sorttext, printer, sort)

如果編譯器報告錯誤就會列出:

pascal:
compilation errors

下一步要做的通常是編輯程序文本:

edit(sorttext)
. . .

並且再次編譯,當編譯成功時,用戶程序可以被直接調用

sort(. . .)

系統也會從其他媒介讀取作業控制命令,例如:

do(tape)

任務是通過在控制檯按響鈴按鈕來搶佔。這會導致系統的重裝和初始化。這個命令開始可以通過任何其他儲存在磁盤上的併發程序替換Solo系統

數據流:

圖一顯示了當用戶通過複製,編輯,編譯,順序處理一個單文本文件時,系統內部的數據流
輸入、 處理和輸出文本同時發生。處理是通過這樣的過程完成的:作業進程通過發送一個參數開始輸入,參數通過緩衝器來傳遞。參數就是輸入設備或者是磁盤文件的名字。
輸入進程通過緩衝區把輸入送往作業進程。在文件的末尾,輸入進程通過作業進程的另一個緩衝區傳遞參數,用來指定在輸入的過程中是否發生了傳輸的錯誤。
輸出通過類似的輸出進程和另一個緩衝區集合來處理。
在單用戶操作系統中,期望能夠以儘可能高的速度處理一個文件。所以,數據被緩衝在內存映像(core)而不是磁盤上,每個緩衝區的容量是512個字符。
這裏寫圖片描述

控制流:

圖二展示了當用戶輸入一個如下的命令時,會發生什麼:

edit(cards, tape)

在系統加載後,機器會執行一個Concurrent Pascal的程序(Solo),他包含了3個進程。最初,輸入和輸出進程均加載,並且當作業進程調用另一個順序程序do時,輸入和輸出進程會調用順序程序io。do程序通過控制檯讀取用戶的命令,並且調用包含兩個參數的edit程序(cards和tape)
編輯器通過發送他的第一個參數給被輸入進程執行的io程序來啓動輸入。這會引發io程序去調用另一個程序cards,cards程序開始讀取卡帶並且把他們送往作業進程。
編輯器通過發送他的第二個參數給被輸出進程執行的io程序來啓動輸出。後者會調用程序tape,tape會從工作進程讀取數據並且把他們放置在磁帶中。
在文件的末尾,cards和tape程序返回io程序,然後等待從作業進程發出的下一步指令。編輯器返回do程序,然後讀取控制檯的下一個命令。
這是值得觀察的:操作系統自身沒有爲各種設備中輸出/輸出提供內置的驅動。數據簡單的通過儲存在磁盤中的順序的Pascal程序來生產和消耗。
操作系統僅僅包含了調用他們的機制。這給用戶提供了完全的自由來增補系統與新的設備並且可以模擬複雜的輸入/輸出像是合併,分割,格式化文件而不改變作業程序。
這裏寫圖片描述
最重要的是順序Pascal程序可以通過任意參數遞歸的調用另一個程序的能力。在圖二中,例如,do程序使用兩個標識符作爲參數調用edit程序。這就不需要一個單獨的(笨拙的)作業控制語言。作業控制語言就是Pascal
這在圖三更鮮顯明的闡明瞭,這句命令

pascal(sorttext, printer, sort)

是怎樣引起do程序來調用pascal程序的。後者依次調用了7個編譯器,一次通過一個,並且(如果編譯的程序正確)pascal最終調用文件系統來儲存生成的代碼。
程序不知道自己被另一個程序調用還是直接被控制檯調用。在圖三中pascal程序調用了文件系統,用戶也可能直接調用文件系統,例如保護他的程序,防止被意外刪除:

file(protect, sort, true)

這裏寫圖片描述
Pascal的指針和堆的概念讓程序擁有在他們之間傳遞任意複雜的數據結構的能力,像是編譯期間的符號表(Jensen 1974)。在大多數情況下,使用標識符,整型和布爾型作爲參數就可以滿足需要。

STORE ALLOCATION(存儲分配):

順序和併發Pascal的運行時環境是一個4K字大小的核心。這是唯一一個使用機器語言寫的程序。用戶通過操作面板將內核(kernel)從磁盤加載到內存映像(core)。內核就會加載solo操作系統並且啓動它。Solo操作系統包含固定數目的進程。他們佔用由編譯器決定的固定數量的核心存儲器(core store)
所有其他的程序都使用順序Pascal編寫。每個進程都在固定的核心段(core segment)儲存了當前執行進程的代碼。當被另一個程序調用的程序結束運行之後,進程重新從磁盤加載前一個程序,並且返回到這個程序。進程使用的數據和被調用的程序都儲存在一個固定長度的常駐內存的內核堆棧(core resident stack)

文件系統:

後備存儲(backing store)是一個由可拆卸包(removable packs)的慢速磁盤。每個用戶都有他自己的磁盤包(disk pack)包含系統和自己的私有文件。所以沒有必要使用分層的文件系統。
磁盤包包含一個儲存在上面的所有文件的目錄。該目錄把自己描述爲一個文件。文件由他的名稱,類型,保護和磁盤地址所描述。文件通過散列(hashing)來查找
所有系統程序在操作輸入文件之前都會檢查他們類型,並且把類型與輸出文件相關聯。例如,順序Pascal編譯器,從ascii文件中提取輸入文件(而不是一個臨時(scratch)的文件),然後把輸出文件變成一個順序碼的文件(sequential code file)。可能的文件類型是scratch,ascii,seqcode和concode
由於每個用戶都有自己的磁盤包,文件需要保護防止被意外覆蓋或刪除。所有的文件初始化是未受保護的。如果想要保護的話,用戶必須從控制檯調用文件系統像是第四節描述的那樣。
爲了避免文件的壓縮(持續幾分鐘),文件頁面被分散在磁盤上並且通過頁面映射來間接尋址(圖4)。文件通過在目錄中查找並且把它的頁面映射放到內核(core)中來打開。
這裏寫圖片描述
Solo系統常駐內存的部分是那些最頻繁使用的文件操作,lookup, open, close, get和put。一個非常駐內存,順序程序,調用文件,處理更復雜並且很少使用的操作:create, replace, rename, protect, 和delete file

DISK ALLOCATION:(磁盤分配)

磁盤總是包含255頁名爲next一個臨時文件。程序通過輸出數據到這個文件來創建新文件。然後他調用文件系統關聯這個數據一個新名字,類型和一個長度(≤ 255)。做完這些文件系統創建next的一個新的實例。
該方案有兩個好處:
1. 所有文件都通過類型化的數據(typed data)初始化
2. 一個程序創建文件僅僅需要調用非常駐內存的文件系統一次(產生該文件之後)。沒有next文件,文件系統就會需要調用兩次:在output創建文件之前和在output定義文件長度之後。
使用單文件next的缺點就是程序同一時間只能創建一個文件
沒使用的磁盤文件被儲存在磁盤上的頁面索引的冪集(powerset)所定義。
在一個慢速磁盤上必須特別注意,讓程序加載快速。如果程序頁隨機散佈在磁盤上,這樣花費16秒鐘來加載編譯器和他的輸入/輸出驅動。在Brinch Hansen(1976c)描述的算法將這一時間減少爲5秒。當系統創建next文件時,他試圖將文件放置在連續的頁,儘可能在相鄰的扇區裏面(但這將會將頁或多或少的分散)。然後重新排列頁面映射內的頁面索引,來最小化加載文件時所需要的磁盤的旋轉和扇區的移動次數。由於這在一個程序被編譯並且儲存到磁盤之前已經完成,這被稱作在編譯器的磁盤調度。
系統將兩個不同的分配技術用於兩個在編譯期間使用到的臨時文件。每次編譯的傳遞都從前驅生成的文件中輸入,並且將輸出放入另一個文件傳遞給後繼。maketemp程序創建這些文件和他們交錯的頁面索引(interleaves their page indices)(making every second page belong to one file and every second one to the other)這使得磁頭通過傳遞(pass)慢慢掃過這兩個文件而不是瘋狂的在他們之間來回移動。
OPERATOR COMMUNICATION:(操作員通信)
用戶通過控制檯來和系統通信。由於任務(例如編輯)通常涉及通過併發執行的多個程序,這些程序必須在被要求輸入或者輸出前讓用戶識別出自己。

do:
edit(cards, tape)
edit:
• • •
do:
• • •

程序標識(program identity)僅僅在每次用戶開始對話(talking to)不同程序的時候顯示。一個程序在不中斷的情況下多次與用戶通訊(例如編輯器)只需認證(identifies)自己一次即可。
通常在同一時間只有一個程序試圖與用戶進行通信(被作業進程執行的當前的程序)。但是輸入/輸出錯誤可能引起另一個進程發出的消息。

tape:
inspect

由於進程很少爭奪控制檯,這足以將進程的獨佔訪問權限給用戶,來輸入或輸出一行。一次會話幾行將很少被打斷。
一個Pascal程序僅僅攜帶身份認證來調用操作系統一次。系統將在需要的時候自動的顯示。

SIZE AND PERFORMANCE:(尺寸和性能)

Solo系統包含由Concurrent Pascal編寫的操作系統和使用順序Pascal編寫的系統程序集。
這裏寫圖片描述
(這兩個Pascal編譯器可被用在使用Concurrent Pascal編寫的不同操作系統裏,而不僅僅是solo)
使用不同編程語言寫的代碼量爲:
這裏寫圖片描述
這就清楚的表明了一個良好的順序編程語言對於操作系統設計比並發語言更加重要。儘管併發程序可能很小,但他似乎仍然值得使用高級語言編寫來確保編譯器可以徹底檢查數據類型和訪問權限。否則,他太容易發生依賴時間的編程錯誤(time-dependent programming errors)這種錯誤很難定位。
內核使用機器語言編寫,實現了Concurrent Pascal的進程和監視器的概念和響應中端。他獨立於運行在上面的特定操作系統。Solo系統需要爲程序和數據提供一個39K字的磁心存儲(core store)。
這裏寫圖片描述
這一數額的空間允許Pascal編譯器來編譯自己。
使用磁盤輸入和磁帶輸出的文本處理速度爲:
這裏寫圖片描述
所有這些任務60—100%磁盤有限(All these tasks are 60–100 per cent disk limited)這些數字不區分花費在等在外圍設備的時間和花費在執行操作系統或用戶代碼,因爲這種區分與用戶無關。他們展示了一個使用高級語言寫的操作系統的總體執行效率,這個系統使用直接的代碼生成並且不經過任何優化。

FINAL REMARKS:(結語)

我和AI Hartmann使用了半年的時間把順序和併發的Pascal編譯器設計並且實現。我使用3個月編寫的操作系統和實用程序。使用機器語言的話,這需要話費20—30個人年(man-years)並且沒有人能夠完全理解。使用一種高效,抽象的編程語言降低開發成本到2個人年並且完成了一個可以由兩個程序員理解的操作系統。
編程成本低讓扔掉笨拙的程序並且重寫他們變得可能。我們這樣做了幾次:早期6道(6-pass)編譯器沒有發佈(儘管他工作很完美),因爲我們發現他的結構太過複雜。第一個使用Concurrent Pascal編寫的操作系統(被稱作Deamy)僅僅用於評估語言的表達能力,並且從未構建(Brinch Hansen 1974)。第二個(被稱作Pilot)使用了幾個月,但是太慢了。
從一個製造商的角度來看,將一個巨大的低效的“通用的”操作系統替換爲一個小的,高效的有特殊用途的操作系統是現實的並且有吸引力。
內核,操作系統,編譯器最初都進行了非常系統的測試,這似乎是正確的。

Acknowledgements:(致謝)

Bob Deverill和AI Hartmann在實現內核(kernel)和Concurrent Pascal編譯器所做的工作對於這個項目是至關重要的。同樣對於Gilbert McCann的鼓勵和支持非常感謝。
Stoy和Strachey(1972)建議在嘗試同時滿足多個用戶之前,應該構建一個好的單用戶操作系統。我發現這是個非常好的建議。我也試圖聽從Lampson(1974)的勸告,同時提供給程序員高層和底層的抽象。
Concurrent Pascal項目由美國國家科學基金會支持。授權號爲DCR74-17331

P. Brinch Hansen 1974. Deamy—A structured operating system. Information Science,
California Institute of Technology, (May), (out of print).
P. Brinch Hansen 1975. The programming language Concurrent Pascal. IEEE Trans. on
Software Engineering, 1, 2 (June).
P. Brinch Hansen 1976a. The Solo operating system: job interface. Software—Practice
and Experience, 6, 2 (April–June).
P. Brinch Hansen 1976b. The Solo operating system: processes, monitors and classes.
Software—Practice and Experience, 6, 2 (April–June).
P. Brinch Hansen 1976c. Disk scheduling at compile-time. Software—Practice and Experience 6, 2 (April–June), 201–205.
K. Jensen and N. Wirth 1974. Pascal–User manual and report. Lecture Notes in Computer
Science, 18, Springer-Verlag, New York.
B. W. Lampson 1974. An open operating system for a single-user machine. In Operating
Systems, Lecture Notes in Computer Science, 16, Springer Verlag, 208–217.
J. E. Stoy and C. Strachey 1972. OS6—an experimental operating system for a small
computer. Comput. J., 15, 2.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章