熟悉而陌生-那些個系統(tǒng)抽象
軟件系統(tǒng)中概念的抽象,是組織思維以加快設(shè)計和構(gòu)建可靠計算的思維結(jié)構(gòu),是計算思維的基本原則。2021年的圖靈獎是對編程語言和編譯器抽象的認(rèn)可,揭示了更高級抽象的進(jìn)展, 這些高級的“系統(tǒng)抽象”來處理大型系統(tǒng)。
然而, 硬幣是兩面的,抽象的好處顯而易見,但那些抽象的緣由較少被提及,抽象的泄漏與缺失更少被人關(guān)注,或許,全面地了解系統(tǒng)抽象才能真正地理解整個系統(tǒng)。從日常中的文件開始,到進(jìn)程與操作系統(tǒng),再到其他的系統(tǒng)抽象,拋磚引玉。
文件的抽象
文件是最常見的數(shù)字對象,是一個字符串的容器,有名稱和大小。文件本身是存儲在磁盤內(nèi)存中的一組固定大小的記錄抽象,它們是以索引表為根的樹形結(jié)構(gòu),而用戶看不到那些記錄、樹和索引表。
“文件管理器”是管理文件的軟件子系統(tǒng),提供了六種基本操作。CREATE 創(chuàng)建一個新文件,DELETE 刪除一個文件。OPEN 將所有文件組件記錄的副本收集到一個主內(nèi)存緩沖區(qū)中的線性文件映像中。CLOSE 將緩沖區(qū)復(fù)制回其組件記錄,并刪除緩沖區(qū)。文件的直接讀取并寫入內(nèi)存結(jié)構(gòu)的速度會較慢,緩沖區(qū)成為了文件管理器管理的又一種類型的對象。READ 操作將打開的緩沖區(qū)中的內(nèi)容復(fù)制到從地址 s 開始的長度為 l 的調(diào)用方內(nèi)存區(qū)域,可以表示為(s,l)。WRITE 操作將數(shù)據(jù)從調(diào)用方的內(nèi)存區(qū)域(s,l)復(fù)制到緩沖區(qū)中,替換緩沖區(qū)中以前的內(nèi)容。
在這里,類型 f 意味著文件能力和類型 b 緩沖區(qū)能力。CREATE 命令創(chuàng)建一個文件,該功能可用作 DELETE 和 OPEN 命令的參數(shù)。OPEN 命令創(chuàng)建了一個可以由 CLOSE、 READ 和 WRITE 命令使用的緩沖區(qū)功能。隱藏在文件管理器中的表用于將文件句柄(fh)映射到磁盤和緩沖區(qū)句柄(bh)映射到主內(nèi)存緩沖區(qū)。
這當(dāng)然是文件系統(tǒng)接口的簡化視圖。真正的文件系統(tǒng)可能有更多的操作,在磁盤上使用更復(fù)雜的樹結(jié)構(gòu),并允許增量讀寫緩沖區(qū)。
進(jìn)程的抽象
也許,操作系統(tǒng)中最基本的抽象是“進(jìn)程”,即執(zhí)行中的程序,進(jìn)程的抽象為了解決早期操作系統(tǒng)的可靠性問題而發(fā)明的。1960年至1965年間,操作系統(tǒng)設(shè)計者著手建造功能強(qiáng)大的計算機(jī)系統(tǒng),可以在大型用戶網(wǎng)絡(luò)中廉價分配計算能力。這些系統(tǒng)旨在整合分時、虛擬內(nèi)存、輸入輸出流、共享文件系統(tǒng)、目錄系統(tǒng)和編程接口等一系列功能。這些功能最大化信息共享,最小化開發(fā)時間,并將CPU 和內(nèi)存資源分給許多用戶。
那時候,大型程序的主要抽象是“模塊和接口”,它要求將復(fù)雜的系統(tǒng)分解成簡單的模塊,通過它們的接口交換信息。例如,一個操作系統(tǒng)可以使用CPU 調(diào)度、內(nèi)存管理、輸入輸出、文件、目錄和編程接口的模塊。然而,無論設(shè)計人員如何仔細(xì)地制定模塊功能和接口,當(dāng)模塊被連接在一起并受制于用戶工作負(fù)載時,系統(tǒng)總是會崩潰,調(diào)試也極其困難。
問題是,模塊是一種控制結(jié)構(gòu),用于指導(dǎo) CPU 一次執(zhí)行一個任務(wù)。然而,操作系統(tǒng)必須為許多用戶管理許多計算。很難將許多用戶同時通過模塊及其接口的工作可視化。大系統(tǒng)不僅僅是擁有更多用戶的小系統(tǒng),多個用戶在實現(xiàn)私有內(nèi)存、共享文件并爭奪有限的 CPU、設(shè)備和內(nèi)存資源,這會涉及到競爭條件、死鎖、繁忙等待、內(nèi)存級別之間的數(shù)據(jù)循環(huán)、文件訪問、用戶通過創(chuàng)建新的自治服務(wù)擴(kuò)展系統(tǒng)、預(yù)測吞吐量和響應(yīng)時間。由此產(chǎn)生了一種新的思維方式,即并發(fā)控制。
進(jìn)程的抽象成為了一個的優(yōu)雅解決方案。進(jìn)程不僅僅是執(zhí)行中的程序,而是一個根據(jù)請求為其他進(jìn)程執(zhí)行服務(wù)的自治代理。進(jìn)程是需要 CPU 時間和內(nèi)存空間的實體,與其他進(jìn)程同步,創(chuàng)建和訪問文件,搜索目錄,響應(yīng)事件,并與其他進(jìn)程結(jié)合以形成動態(tài)所謂計算結(jié)構(gòu)。
進(jìn)程的抽象結(jié)果產(chǎn)生了另一個重要的抽象概念ーー非終止計算,服務(wù)流程被設(shè)計成無盡循環(huán)(while true)。在完成請求之后,服務(wù)流程將返回到“原點”,并等待下一個傳入請求。隱藏在后臺的守護(hù)進(jìn)程執(zhí)行有益的管理功能,例如回收內(nèi)存或?qū)⑿薷暮蟮膬?nèi)存內(nèi)容寫回磁盤。從連續(xù)運行計算系統(tǒng)的角度來設(shè)計,操作系統(tǒng)被視為一個協(xié)作的社會,大多是非終止的進(jìn)程,而不是堆積如山的模塊。
相比之下,目前大多數(shù)編程類的應(yīng)用成為了獨立啟動和終止的程序, 是從輸入開始,到輸出結(jié)束的程序。在這種情況下,非終止程序的進(jìn)程看起來像一個 無限循環(huán)的bug。
操作系統(tǒng)的抽象
操作系統(tǒng)可以描述為一個“抽象機(jī)器”,其指令集是在接口中提供的操作,隱藏了內(nèi)部數(shù)據(jù)結(jié)構(gòu)跟蹤所有對象。文件管理器就是一個例子。在操作系統(tǒng)或網(wǎng)絡(luò)中,可以將功能抽象成一系列的層次。每個層次都可以由在較低層次上定義的抽象組成,但不能使用任何在較高層次上的抽象信息。
第一個操作系統(tǒng)的分層實例是 Edsger Dijkstra 大約在1965年設(shè)計的,抽象為以下邏輯層次:
- Interrupts and stacks:中斷和堆棧
- Processes and semaphores:進(jìn)程和信號量
- Virtual memory:虛擬內(nèi)存
- Message exchange:信息交換
- Internet naming:網(wǎng)絡(luò)命名
- I/o 流:文件、管道、設(shè)備
- Directories :目錄
- Virtual machines :虛擬機(jī)
- user interface :Shell (用戶界面)
- Services:服務(wù)
1-5是微內(nèi)核,程序以內(nèi)核模式運行,可以訪問所有內(nèi)存。級別6-10是用戶內(nèi)核,程序在用戶模式下運行,并且只能訪問自己進(jìn)程的私有內(nèi)存。每個級別都是一個抽象機(jī)器,用于管理該級別的對象類。第10層是內(nèi)核外部用戶服務(wù)的集合,例如內(nèi)核圖形用戶界面、應(yīng)用程序和性能分析工具。每個用戶服務(wù)都有自己的系統(tǒng)抽象。
對象和操作由較低級別的對象和操作組成。實際上,一個層次的抽象機(jī)器被嵌套起來,以便上一級別使用。抽象機(jī)器的用戶界面由所有嵌套機(jī)器的聯(lián)合組成。這種嵌套隱藏了較低級別的細(xì)節(jié),令很多人茫然不解。
在這個抽象分層中,程序必須設(shè)計成只調(diào)用下面的層次,而不向上調(diào)用,免了循環(huán)等待和自引用代碼的循環(huán),并使系統(tǒng)能夠在一個分層上被證明和測試。例如,假設(shè)文件管理器將文件用作目錄的容器,這似乎需要從文件管理器(Level 6)向上調(diào)用目錄管理器(Level 7) ,請求創(chuàng)建文件管理器可以填充的目錄。為了避免向上調(diào)用,我們將創(chuàng)建目錄并用文件填充它的職責(zé)移到 shell (Level 9)。Shell 可以調(diào)用 Level 7創(chuàng)建目錄,然后調(diào)用 Level 6將文件加載到目錄中。這種思維方向的重新定位簡化了代碼,并消除了循環(huán)性帶來的任何問題。
分層的系統(tǒng)抽象異常的強(qiáng)大,并沒有因為簡單化和過度約束使得功能缺失,但這些約束確實引入了更多的復(fù)雜性。毫無疑問,分層的系統(tǒng)會產(chǎn)生更小的內(nèi)核。較小的內(nèi)核更快,更容易測試和驗證。如今,唯一可證明安全的操作系統(tǒng)是通過抽象分層構(gòu)造的。
系統(tǒng)抽象
系統(tǒng)的抽象對于構(gòu)建具有大量進(jìn)程、用戶、設(shè)備和網(wǎng)絡(luò)連接的大型復(fù)雜系統(tǒng)是必不可少的。每個主要的計算系統(tǒng)領(lǐng)域都有自己的特征抽象。例如,互聯(lián)網(wǎng)有 IP 協(xié)議用于尋址主機(jī),TCP 協(xié)議用于克服嘈雜的傳輸,域名,url,網(wǎng)頁,標(biāo)記語言等等。
云服務(wù)中具有通用的無限名稱空間、存儲文件的不可偽造的指針、數(shù)據(jù)中心、防止數(shù)據(jù)丟失的冗余等等。數(shù)據(jù)庫系統(tǒng)具有記錄、字段、表、投影、連接、查詢、原子事務(wù)、持久存儲、文件對存儲的永久承諾等等,不勝枚舉。
計算系統(tǒng)的一個主要復(fù)雜性來源是大量的數(shù)字對象。系統(tǒng)抽象通過兩種方式簡化了這種復(fù)雜性。首先,將所有相同類型的對象組合到一個類中,并為所有這些對象設(shè)計一個管理器。管理器為允許進(jìn)程在這些對象上執(zhí)行的操作提供了一個接口。其次,類管理器為對象分配唯一的名稱,并驗證每個訪問權(quán)限,必須保護(hù)包含這些名稱和訪問代碼的指針不被更改。
在操作系統(tǒng)和云存儲中,通過一種稱為“capability”的較低級別的抽象,由類型、訪問、句柄等字段組成,Type 字段指示指向的對象類型,訪問字段是一個多位代碼,它指定可以在該對象上執(zhí)行類操作的哪個子集,句柄字段是對象的唯一代碼,它將對象與同類型的所有其他對象區(qū)分開來。只要“capability”保持在內(nèi)核空間中,它們就是受保護(hù)的,因為沒有任何用戶進(jìn)程能夠改變內(nèi)核空間中的任何內(nèi)容。當(dāng)它們被傳遞到外部時,它們被加密校驗和所增強(qiáng),使收件人能夠確認(rèn)它們自創(chuàng)建以來沒有被更改。事實上,“capability”已經(jīng)成為了實現(xiàn)面向?qū)ο缶幊陶Z言的原則。
小結(jié)
系統(tǒng)抽象是用來設(shè)計和研究大規(guī)模、復(fù)雜的信息系統(tǒng)的工具之一。軟件的驚人進(jìn)步一般都是通過系統(tǒng)抽象實現(xiàn)的,然而,很少有大型程序抽象的解析說明,也缺少系統(tǒng)抽象的緣由介紹。如果沒有這些高級的抽象概念,不了解這些抽象的得失,很可能是一種缺憾。