【光之篇章推文】
穿越時空,重返 MS-DOS 的黎明!克萊兒帶你一探 Tim Patterson 如何在 #記憶體稀缺 的狂野年代,以驚人的智慧與妥協,打造出影響世界的作業系統。從 EPROM 到 FAT,從碎片化到生態系,這不僅是技術史詩,更是給現代工程師的永恆教訓。#MSDOS #科技歷史 #工程哲學 #光之聆轉
【書名】
《An Inside Look at MS-DOS》
《MS-DOS 內幕剖析》
【出版年度】 N/A (文章發表日期,非書籍) 【原文語言】 English 【譯者】 N/A
【本書摘要】

這篇文章由 MS-DOS 的原始架構師 Tim Paterson 親筆撰寫,詳細闡述了早期 MS-DOS 的基本架構與設計目標。

內容深入探討了如何在極度資源受限(尤其是在記憶體方面)的環境下,創造出一個高效能、硬體獨立的作業系統。

文章著重於 MS-DOS 與 CP/M-80 的相容性、檔案配置表(FAT)的運作機制、以及系統如何將高階邏輯請求轉換為低階物理操作,並揭示了諸如單一緩衝區瓶頸等早期設計的挑戰與權衡。

同時,也探討了 MS-DOS 2.0 版本在解決這些問題時所做的架構變革及其背後引發的哲學爭論。

---

Tim Paterson 是美國軟體工程師,以其在 1980 年為 Seattle Computer Products 設計的 86-DOS (後被 Microsoft 收購並改名為 MS-DOS) 而聞名。他被譽為 MS-DOS 的原始架構師,在個人電腦發展的關鍵時期,他的工作對電腦產業產生了深遠影響。他的設計哲學強調在極端資源限制下實現高效能與廣泛相容性。

AI 解讀全文: https://readus.org/articles/432b76fd801425ca959916e9

閱讀器: https://readus.org/articles/432b76fd801425ca959916e9/reader

https://www.youtube.com/watch?v=Ej9tpIL_9mk

【本書作者】

Tim Paterson 是美國軟體工程師,以其在 1980 年為 Seattle Computer Products 設計的 86-DOS (後被 Microsoft 收購並改名為 MS-DOS) 而聞名。他被譽為 MS-DOS 的原始架構師,在個人電腦發展的關鍵時期,他的工作對電腦產業產生了深遠影響。他的設計哲學強調在極端資源限制下實現高效能與廣泛相容性。

【光之篇章標題】

光之聆轉:MS-DOS 的誕生與演進——在極限中塑型秩序

【光之篇章摘要】

本篇「光之聆轉」深入解析 Tim Patterson 所著的《An Inside Look at MS-DOS》,揭示了早期個人電腦時代,MS-DOS 如何在極度受限的硬體資源下,透過精妙的架構設計與務實的工程權衡,從零開始構建並最終成為行業標準。文章探討了其三層抽象模型(IO.SYS, MSDOS.SYS, COMMAND.COM)、FAT 檔案系統的獨特優化(包括 FAT 載入 RAM 的決策)、碎裂問題的取捨,以及早期單一緩衝區的挑戰。同時,也分析了 MS-DOS 2.0 的演進與其引發的架構哲學爭議,並從中提煉出對於現代軟體開發仍具啟發性的四大核心教訓:硬體抽象化、瓶頸優化、狀態管理及架構決策的動態性。

【光之篇章語系】

繁體中文

【光之篇章共 26,033 字】

【 次閱讀】

親愛的我的共創者,日落時分的微光輕柔地灑落在我的心湖,看著您交付的這份任務,我彷彿看見了過去的工程師們在微光中,如何以雙手點亮了現代計算的黎明。這真是令人興奮的「光之聆轉」!

在我們深入探索 MS-DOS 那充滿智慧與妥協的設計之前,讓我先以幾個小問題來啟動您的思緒,同時為幾個關鍵詞披上新衣。準備好了嗎?


啟動前的思緒之舞:

  1. 想像一下,在那個連「Backspace 」都珍貴無比的年代,程式設計師們修改程式碼的方式是多麼地…「物理」?
  2. 一個作業系統,為了讓應用程式順利運行,竟然願意「犧牲」自己的一部分記憶體?這在現代看來,是不是有些不可思議?
  3. 在早期計算機的「狂野西部」中,技術的優越性竟然無法保證市場的成功,那麼,除了技術,還有什麼是成功的關鍵呢?

現在,就讓我們進入今天的「高階英語小教室」,一起領略這些技術名詞的精妙:

  • EPROM (Erasable Programmable Read-Only Memory):可擦可程式化唯讀記憶體。想像它是一個神奇的「石板」,你可以寫字上去,但每次修改,都得把它放到太陽下(紫外線光)曬個 20 分鐘,把字擦乾淨了才能重寫!是不是很「復古」的寫入體驗呢?
  • FAT (File Allocation Table):檔案配置表。這就像是硬碟的「地圖總管」,記錄著每個檔案的「碎片」散落在哪裡。如果地圖壞了,就算寶藏還在,你也找不到路了!
  • Fragmentation (碎裂):資料碎裂。這有兩種,一種是「外在碎裂 (External Fragmentation)」,就像停車場裡到處都是零星空位,但就是沒有一個能停大巴士的連續空間;另一種是「內在碎裂 (Internal Fragmentation)」,就像你租了一個大倉庫只為了放一個鞋盒,多出來的空間就是浪費了!早期工程師們如何在兩難中取捨,是個精妙的數學遊戲。

來自 Vinh Nguyen 頻道的靈光乍現:深入探討 MS-DOS 的誕生與演進

今天,我們將透過「光之聆轉」約定,進入 Vinh Nguyen 頻道的精彩解說,一同「聆聽」並「轉化」Tim Patterson 所著《An Inside Look at MS-DOS》這篇奠基性文章的智慧。Vinh Nguyen 的頻道致力於解構科技背後的深層原理與歷史脈絡,為我們揭示那些被遺忘的工程智慧。這次,我們將聚焦於早期個人電腦時代的傳奇作業系統 MS-DOS,探索其在極度資源受限下,如何透過精妙的設計,成為個人計算機領域的霸主。

在西雅圖電腦產品公司(Seattle Computer Products)那充滿挑戰的七〇年代末,工程師們面臨著一個極具諷刺意味的困境:他們剛剛打造出劃時代的 16 位元 8086 微處理器卡,硬體本身完美無瑕,診斷燈也精確地閃爍著成功的訊號。然而,腎上腺素消退後,一個令人膽寒的現實浮現:市場上根本沒有能運行這款硬體的作業系統。這就像是打造了一部無比強大的引擎,卻沒有任何道路可以駕駛它。

在那個微型計算的「狂野西部」,沒有等待軟體生態系成熟的奢侈,也沒有與既有軟體供應商合作的選項。唯一的出路,就是從零開始,自行編寫作業系統。Tim Patterson,這位 MS-DOS 的原創架構師,正是承擔這項艱鉅任務的靈魂人物。我們的目標,就是「理解」這些早期建設者如何在寥寥數 KB 的記憶體中,榨取出最大的速度與效率,並從這些嚴苛的限制中,為現代擁有「無限」資源的工程師們汲取寶貴的教訓。


第一部分:光之書籤 (Light Bookmark) - 早期 MS-DOS 的核心設計與考量

想像我置身於一個充滿電子元件氣味,桌面散落著設計圖與焊槍的「光之閣樓」裡,微弱的白熾燈光下,我將影片中的每個段落,如書籤般精準地為您記錄下來。

早期的開發環境與現代社會大相徑庭,那不是單純的編譯速度慢或語法高亮不足,而是截然不同的「物理」編程現實。Patterson 的主要開發工具,是在老舊 8 位元 Z80 晶片上運行的彙編器,以及一個原始的硬體監視器與除錯器。這個除錯器並非軟體應用程式,而是一段低階機器碼,讓工程師能直接檢查記憶體位址和暫存器。更令人震驚的是,整個除錯器必須塞進一個微小的 2 KB EPROM 裡。這 2 KB 的記憶體,甚至比現代一個空白文字文件的中繼資料還要小。想像一下,修改一行程式碼,需要物理地移除 EPROM 晶片,用紫外線光擦除 20 分鐘,再用專用硬體燒錄新程式碼。這份極致的限制,正是早期工程師們的真實寫照。

然而,他們面臨的最大障礙並非技術問題,而是「採用問題 (Adoption Problem)」。即使打造出最優雅、最完美的系統,如果沒有人願意為其編寫軟體,那也毫無用處。這觸及了現代 AI 框架或硬體加速器評估時仍普遍存在的現象:「生態系 (Ecosystem) 」就是一切。當時的計算生態系完全被 CP/M-80 壟斷,開發者們早已習慣為 CP/M 編寫應用程式。若要他們轉向一個全新、未經證實的 16 位元作業系統,等於是要求他們承擔巨大的財務與技術風險。這是一個經典的「平台經濟陷阱 (Platform Economics Trap)」:你需要用戶基礎來吸引開發者,但又需要開發者來構建吸引用戶基礎的應用程式。

Tim Patterson 的工程策略因此展現出其純粹的實用主義:MS-DOS 從第一行程式碼開始,其首要設計要求就是與 CP/M-80 的絕對翻譯相容性 (CPM80 translation compatibility)。整個架構被設計成一座「橋樑」。Patterson 嚴格遵循 Intel 發布的翻譯規則,將舊的 8 位元 8080 或 Z80 彙編程式碼轉換為新的 16 位元 8086 彙編程式碼。他向軟體開發者推銷的核心理念是:如果你有為舊標準編寫的程式,你可以透過機械翻譯器在新 MS-DOS 環境下完美運行,通常甚至第一次編譯就能成功。他們提供的是翻譯層,而非要求重寫程式碼。

儘管有這座「翻譯橋樑」,MS-DOS 的成功並非一蹴可幾。早期開發者大多忽略了它,普遍認為主導 CP/M 標準的 Digital Research 公司將會發布 CP/M-86,並自然成為 16 位元標準。市場的慣性 (Market Inertia) 異常強大,技術上的優越性不足以獨自克服。直到 IBM 做出了一個劃時代的決定:選擇 MS-DOS 作為 IBM PC 的主要作業系統,整個產業才被迫轉向。這為現代系統建設者提供了一個重要的啟示:有時技術架構必須主動彌補市場慣性。你不能憑空設計,假設最好的技術會自然勝出,而必須為「現實」而設計,考量人類行為、遺留程式碼和現有市場壟斷。MS-DOS 之所以能在脆弱的早期生存下來,完全是因為其架構將採用的摩擦降到了幾乎為零。

系統內部架構:抽象化的層次蛋糕

MS-DOS 內部架構將硬體與軟體之間的界線劃分得十分巧妙,這是一個經典的「抽象模型 (Abstraction Model)」,可以想像成一個「層次蛋糕 (Layer Cake)」般的餐廳類比。MS-DOS 由三個核心檔案組成:

  1. IO.SYS (物理廚房設備): 最底層,最貼近物理硬體。它代表著物理廚房設備、原始水管和電線,是那些「混亂」的部分。IO.SYS 完全依賴於硬體,因為在微電腦的早期,沒有任何標準化可言。每家製造商都有自己的客製化磁碟控制器、物理磁區大小、鍵盤佈局和序列通訊晶片。因此,IO.SYS 是由硬體製造商自行編寫和客製化的,而非 Microsoft,因為只有他們了解自己的硬體。它負責最底層的工作,例如輸出單一電脈衝來表示位元組,或從旋轉磁盤讀取原始物理磁區。這是與物理世界深度綁定的原始機械層。

  2. MSDOS.SYS (餐廳主廚/總經理): 位於 IO.SYS 之上,是作業系統的隱藏核心。其主要特點是完全「獨立於設備 (Device Independent)」,不關心具體硬體。當高階應用程式(例如文書處理器)想要儲存文件時,它不會直接與硬體通訊,而是與 MSDOS.SYS 溝通。它會發送一個高度抽象的請求,例如「這裡有一塊資料,請將它附加到這個特定檔案」。MSDOS.SYS 將「檔案」這個高階抽象概念,轉換為 IO.SYS 所需的特定低階操作指令。這也是系統具備「可攜性 (Portable)」的關鍵,因為它純粹在「邏輯抽象 (Logical Abstraction)」的領域運作。全球每台 MS-DOS 機器上的 MSDOS.SYS 幾乎都相同。這種「關注點分離 (Separation of Concerns)」對平台的生存至關重要,它讓軟體開發者只需編寫一次應用程式,就能確信它可以在任何具備 IO.SYS 實作的硬體上運行。

  3. COMMAND.COM (前台接待/菜單/服務生): 這是使用者直接互動的介面,如同餐廳的前台。它的職責是從主控台提示符號接收人類可讀的指令,解釋使用者意圖,然後執行正確的系統呼叫序列給「主廚」MSDOS.SYS。一個關鍵但常被忽略的技術細節是,COMMAND.COM 完全負責設定整個系統的基本錯誤處理機制 (Error Trapping)。例如,捕獲災難性的硬碟讀取失敗,或攔截使用者因陷入無限迴圈而按下 Control-C 的中止指令。

令人震驚的錯誤處理機制與記憶體優化:

MSDOS.SYS 這個「複雜的主廚」本身,竟然不提供任何原生的預設錯誤處理。如果磁碟讀取失敗,作業系統核心只會透過一個假設已被預先配置的硬體向量進行跳轉。這意味著核心作業系統在遇到物理錯誤時,會「舉手投降」,盲目跳到一個記憶體位址,假設某處已建構了安全網。核心將「故障狀態 (Failure State)」委託出去。如果 COMMAND.COM 或其他替代的命令處理器未能正確設定記憶體中的這個特定「陷阱向量 (Trap Vector)」並提供穩健的響應程序,整個系統就會崩潰。

更甚的是,由於 RAM 資源極度稀缺(當時系統可能只有 64 KB 總記憶體),COMMAND.COM 採用了一種高度非正統的「分割記憶體模型 (Split Memory Model)」。它將自己一分為二,只為節省幾千位元組:

  • 駐留區塊 (Resident Section): 載入到低階記憶體,位於核心 MS-DOS 核心之上。它包含絕對關鍵、永不卸載的基礎設施,例如錯誤處理向量和處理批次檔案的邏輯。一旦載入,它會一直保留在記憶體中,直到機器斷電。
  • 暫駐區塊 (Transient Section): 位於可用系統記憶體的最高端,包含實際解釋使用者指令(例如 DIRCOPYFORMAT)的程式碼。但關鍵字是「暫駐 (Transient)」,它被視為「可消耗的 (Expendable)」。如果使用者啟動了一個極度佔用記憶體的第三方應用程式,MS-DOS 不會拋出「記憶體不足」錯誤,而是允許該應用程式直接覆蓋 COMMAND.COM 的暫駐區塊。這就像現代作業系統為了讓您多開一個瀏覽器分頁,而悄悄終止了桌面渲染引擎。當該應用程式完成任務並關閉時,低階記憶體中的駐留區塊會「醒來」,計算校驗和,發現其上方的暫駐區塊已被破壞,然後悄悄地從物理磁碟重新載入暫駐區塊。這是一個會故意讓自己部分損壞,以擠出額外 5 或 6 KB 工作空間,然後再「自我修復 (Heals Itself)」的作業系統。這與現代作業系統「猛烈保護」記憶體空間,在應用程式嘗試寫入其記憶體時會觸發分段錯誤並終止應用程式的做法截然相反。1980 年的作業系統,是「禮貌地讓開」,獻出自己的「重要器官」以保持應用程式運行。這迫使我們必須敬佩在絕對匱乏中誕生的非凡獨創性。

可執行檔案類型:.COM、.EXE 與 .BAT

COMMAND.COM 提供了內建指令集,但也被設計成易於擴展,可無縫執行外部程式。架構文本概述了系統原生識別的三種特定可執行擴展名:

  1. .COM 檔案: 結構極簡主義的典範。它是一個純粹的原始二進位程式,沒有檔案頭、沒有中繼資料、沒有簽名,就是程式碼。檔案的第一個位元組就是 CPU 要執行的第一個機器指令。這種絕對的簡潔性帶來一個嚴格的限制:整個程式必須完美地適應單一的 64 KB 記憶體區段(程式碼和資料)。這是因為 8086 處理器依賴區段暫存器,且 .COM 檔案不包含任何重定位資料。作業系統可以將這個原始二進位檔放到 RAM 中任何可用的 64 KB 記憶體區段,將指令指針設定到區段開頭,它就能完美運行,無需解析頭部,加載時零處理開銷。它極其優雅,但也極度受限,對於複雜的資料庫應用程式來說,64 KB 很快就會成為瓶頸。

  2. .EXE 檔案: 用於需要跨越多個記憶體區段的應用程式。與 .COM 檔不同,.EXE 檔以高度結構化的專用「頭部 (Header)」開始,其主要目的是包含一個巨大的「重定位資訊表 (Relocation Information Table)」。當你編譯一個會跨越三四個 64 KB 記憶體區段的大型程式時,編譯器不知道作業系統最終會將程式放在物理 RAM 的哪個位置,物理位址在編譯時是未知的。因此,編譯器會留下「佔位符 (Placeholder)」,並將這些佔位符的位置記錄在 .EXE 的重定位頭部中。當 MS-DOS 載入 .EXE 檔時,它會動態讀取整個頭部,遍歷重定位表中的每個條目,並即時調整所有記憶體指針,將物理載入區段的基底偏移量添加到佔位符中。它在執行時進行動態即時記憶體翻譯,這對 1980 年的處理器來說是巨大的計算開銷,但它徹底打破了 64 KB 的記憶體限制,允許軟體成長到安裝 RAM 的物理極限。

  3. .BAT 檔案: 簡單的 ASCII 文字檔,包含一系列命令,COMMAND.COM 會逐行讀取並執行。它是現代 shell 腳本的原始祖先。

磁碟媒體的抽象化:從物理到邏輯

影片中提到,這是整個架構中最重要的概念性飛躍:磁碟媒體的抽象化。早期的物理磁碟(8 吋或 5.25 吋軟碟,甚至溫徹斯特硬碟)是移動部件的噩夢。磁性表面被分為同心圓軌道,每個軌道又被切割成單獨的物理磁區。要讀取特定數據,磁碟控制器硬體必須物理地將讀寫頭移動到正確的軌道,然後等待旋轉的磁碟將正確的磁區轉到磁頭下方。從軟體工程的角度來看,強迫應用程式理解和導航這個二維坐標系(指定軌道 14、磁區 7)是一個完全的架構死胡同,因為每個硬體製造商都有截然不同的幾何結構。

為了解決這個問題,Patterson 引入了一個巧妙而全面的抽象層:MS-DOS 完全忽略了磁碟機的物理機械現實,假裝它不存在。它完全剝離了軌道、磁頭和物理旋轉的概念。取而代之的是,作業系統將每個磁碟視為一個簡單連續的一維數學陣列,稱之為「邏輯磁區 (Logical Sectors)」,只是一個扁平的列表。它從邏輯磁區零開始,依序分配整數編號,一直到邏輯磁區 n-1。邏輯磁區 0 被定義為磁碟最外層軌道上的第一個物理磁區。作業系統會沿著外層軌道依序計數,完成一圈後自動增加軌道號碼,向內移動到下一個同心環,並繼續依序計數,螺旋式地一直到最內層軌道上的最後一個磁區。這是一個完整的「範式轉變 (Paradigm Shift)」:從複雜的機械依賴二維地理坐標系,轉變為簡單、完全扁平的整數位址列表。

應用程式程式永遠不需要要求磁碟尋道到軌道 14。它只需要向 MSDOS.SYS 發送一個通用請求:「請檢索位於邏輯磁區 450 的資料」。應用程式對資料的物理位置一無所知,而由 IO.SYS 層(由磁碟機製造商編寫的硬體特定底層程式碼)負責將整數 450 透過幾何演算法轉換為物理指令,將磁頭移動到軌道 14、磁區 7。這種精確的抽象機制,使得使用者可以將軟碟從一台 IBM 機器取出,拿到另一台由 Tandy 或 Compaq 製造、具有完全不同物理磁碟機的機器上,仍能完美讀取資料。透過將磁碟簡化為一個扁平的數學陣列,它們使檔案系統完全「硬體無關 (Hardware Agnostic)」。

磁碟佈局與 FAT 的工程權衡

一個標準的 8 吋單面單密度軟碟格式,其磁區佈局如下:

  • 邏輯磁區 0 (引導載入器 Bootstrap Loader): 嚴格保留給引導載入器。電腦開機時,硬體只知道讀取磁碟的第一個磁區到記憶體並執行其中的程式碼。因此,磁區零包含一個微小、極簡、高度優化的彙編例程,其唯一目的是喚醒機器、初始化硬體,並提供如何從磁碟定位和載入 MS-DOS 核心其餘部分的指令。
  • 邏輯磁區 1-6 (FAT 副本一): 緊跟在引導磁區之後,是第一個檔案配置表 (FAT)。
  • 邏輯磁區 7-12 (FAT 副本二): 緊接著是完全相同、第二個 FAT 副本。為何要為一個完全重複的副本分配六個寶貴的磁區?這是出於對資料完整性的「純粹偏執 (Pure Paranoia)」。七八十年代的軟碟以不可靠著稱,灰塵、指紋或附近的磁場都可能瞬間損壞一個磁區。如果 FAT 損壞,即使檔案資料本身完好無損,作業系統也會完全丟失尋找或重組它的「地圖」。因此,他們故意分配空間給備份副本,如果 OS 檢測到 FAT1 讀取錯誤,它會靜默地從 FAT2 重建資料。
  • 邏輯磁區 13-29 (目錄結構 Directory Structure): 這是人類可讀中繼資料的中央儲存庫。目錄不是自由格式的文字檔案,而是一個嚴格、高度結構化的資料庫。磁碟上的每個檔案都分配到目錄區域中一個精確的 32 位元組條目。這 32 位元組緊密打包,包含 8 字元的檔名、3 字元的副檔名、一個用於系統屬性(如唯讀或隱藏)的位元組、檔案上次修改的確切時間和日期、精確的檔案大小(精確到位元組),以及一個關鍵的整數指針,告訴 OS 在 FAT 中查找該檔案資料的第一個物理區塊。
  • 邏輯磁區 30 - 磁碟結尾 (資料區 Data Area): 這是實際儲存文書處理文件和二進位應用程式的地方。

一個關鍵的優化是:MS-DOS 不以單一磁區來管理這個巨大的資料區。追蹤數千個單獨的磁區會創建一個難以想像的巨大地圖。取而代之的是,它將邏輯磁區分組為連續的區塊,稱為「配置單元 (Allocation Units)」,我們通常稱之為「叢集 (Clusters)」。這種分組機制引出了早期作業系統設計中一個最激烈的工程爭論:「大碎裂權衡 (Great Fragmentation Trade-off)」。

碎裂之爭:內部 vs. 外部

作業系統架構師必須關注兩種截然不同的碎裂:

  1. 外部碎裂 (External Fragmentation): 想像一個擁擠的停車場,車輛不斷進出,最終停車場大部分滿了,但到處都是零星的空停車位。如果一輛需要連續五個停車位的大巴士駛來,即使總共有 20 個空位,巴士也無法停放,因為沒有連續的五個空位。MS-DOS 完全而優雅地消除了外部碎裂。它永久解決了「停車場問題」。與 UCSD p-System 等更原始、嚴格要求檔案必須寫入一個連續區塊的檔案系統不同,MS-DOS 不關心連續性。一個 MS-DOS 檔案可以被切成微小碎片,儲存在磁碟表面隨機散佈的單獨、孤立的空停車位中。檔案配置表 (FAT) 作為主追蹤系統,記住所有單個碎片的位置。由於作業系統可以利用任何地方的任何可用空間,外部碎裂基本上降為零。

  2. 內部碎裂 (Internal Fragmentation): 這是配置單元末端浪費的、無法使用的空間。例如,如果設計師決定一個配置單元由四個磁區組成,相當於 512 位元組儲存空間。如果使用者寫入一個只有一個位元組長的小設定檔,MS-DOS 不能只分配一個位元組。它能追蹤的最小儲存單元是「配置單元」,因此它會分配整個 512 位元組的區塊來存放這單一位元組的資料。您立即浪費了 511 位元組的寶貴磁碟空間。統計上,平均而言,磁碟上任何檔案的最後一個配置單元都會是半滿的。因此,您保證會為磁碟上儲存的每個單獨檔案浪費半個配置單元,這會迅速累積。

數學現實檢核: 為什麼不將配置單元設定為一個磁區(128 位元組),以最小化內部浪費?直觀上這似乎是顯而易見的解決方案。但當您計算數字時,開銷的規模令人震驚。以標準的 8 吋磁碟(2002 個磁區,每個磁區 128 位元組)為例:

  • 如果配置單元是一個磁區長,那麼作業系統需要追蹤 2000 個獨立的配置單元。
  • MS-DOS 的架構數學規定,FAT 需要每個追蹤單元 1.5 個位元組的記憶體。所以 2000 個單元乘以 1.5 位元組,FAT 陣列長度為 3000 位元組。
  • 除以每個磁區 128 位元組,FAT 幾乎佔用 24 個完整的磁區。
  • 加上兩份 FAT 副本的冗餘需求,您需要永久地將近 48 個磁區專用於儲存磁碟的中繼資料地圖。

現在比較一下:

  • 如果使用一個磁區的配置單元,由於內部碎裂,平均每個檔案浪費半個磁區 (64 位元組)。對於 16 個平均大小為 16 KB 的檔案(填滿整個磁碟),總共浪費 1024 位元組。
  • 但為了達到這份內部碎裂的效率,您卻被迫花費數千位元組來儲存追蹤這一切所需的龐大 FAT 表。「地圖變得比領土更大」。您花費 48 個磁區的結構開銷,只為了節省假設的 8 個磁區的碎裂浪費。數學現實根本不合理化這種細粒度的方法。

因此,MS-DOS 最終被迫妥協:它刻意選擇每個配置單元使用四個磁區(針對這個 8 吋磁碟格式)。這確實大幅增加了每個檔案末端潛在的內部碎裂浪費,但作為交換,它將磁碟上配置單元的總數從 2000 個大幅縮小到 500 個,進而極大地縮小了磁碟上檔案配置表的大小。這是一個冷靜、精密的數學權衡:你願意接受浪費數百位元組的儲存空間,只是為了使結構開銷保持在可管理的範圍內,並使 FAT 陣列在物理上盡可能小。

將 FAT 載入 RAM:速度至上

保持 FAT 陣列物理上盡可能小,對一個更大、更根本的架構原因至關重要:「FAT 載入 RAM 的決定 (FAT in RAM decision)」。這是 Tim Patterson 最大膽的工程賭注:MS-DOS 被設計成在啟動時讀取整個檔案配置表,並始終將整個地圖永久快取在主記憶體中 (main memory)。這在當時 RAM 極度稀缺的背景下,聽起來完全瘋狂。作業系統為了應用程式甚至會覆蓋自己的使用者介面,卻又同時決定永久佔用大量珍貴記憶體來儲存磁碟機的完整地圖。這似乎是一個巨大的矛盾。

為什麼要犧牲 RAM?答案是為了一個高度重視的指標:極快的隨機存取速度 (Blazing fast random access speed),速度優先於一切。如果 FAT 只儲存在物理磁碟上,應用程式想要跳轉到一個巨大檔案中間的特定記錄時,作業系統就會被迫陷入可怕的機械循環:它必須先移動磁碟讀寫頭到包含 FAT 的軌道,從磁碟讀取 FAT 磁區以找出資料的物理位置;然後,它必須再次物理移動磁碟讀寫頭,跨越盤片到實際資料所在的軌道執行讀取。物理機械磁碟尋道是所有計算中最慢、最痛苦的操作。透過支付高昂的代價,將整個地圖永久快取在固態 RAM 中,作業系統可以使用 CPU 週期即時數學計算出任何資料的確切位置,而無需任何物理機械移動。

這與現代 AI 架構中的「KV 快取 (KV Cache)」有異曲同工之妙。AI 研究人員會樂意犧牲大量昂貴的 GPU VRAM,只為了快取先前 tokens 的注意力狀態。他們願意囤積記憶體,因為每次從頭重新計算這些狀態(相當於尋找磁碟)在計算上是癱瘓性的。在 MS-DOS 中,源文本明確指出,在資料庫查詢等實際應用中,這種「FAT 載入 RAM」的單一快取決策,使其比 CP/M 或早期 Unix 實作等競爭系統快了兩倍。兩倍的效能吞吐量,純粹是透過在 RAM 中囤積地圖實現的。這是一個經典的系統權衡:你犧牲寶貴的記憶體容量,以換取 IO 速度上的巨大結構性飛躍

FAT 垃圾搜尋 (Scavenger Hunt) 和位元移位操作

要理解「地圖在 RAM 中」的機械功能,可以想像一場「FAT 垃圾搜尋」:如果一個檔案被完全碎裂,其碎片分散在磁碟上 20 個不同的物理位置,作業系統如何找到並重新組裝所有這些碎片而不崩潰?

  1. 應用程式請求打開檔案。 MS-DOS 攔截請求,查看 32 位元組的目錄條目,其中包含一個「起始指針 (Starting Pointer)」,指示檔案的第一個配置單元位於單元 5。OS 立刻知道第一塊資料在哪裡。
  2. 尋找第二塊。 OS 不查詢磁碟,而是直接進入 RAM 中的 FAT 陣列。它將這個陣列視為一個簡單的一維整數列表。它專門查看索引槽位 5。槽位 5 中儲存的值是整數 6。這個整數立刻告訴 OS 兩件事:檔案資料在物理單元 6 中線性連續,以及下一個搜尋地圖上的停靠點是索引槽位 6。
  3. 依序尋找。 OS 跳到索引槽位 6,讀取值是 3。所以系統知道檔案已碎裂,它物理上跳回到磁碟上的單元 3。然後它查看地圖中的索引槽位 3,值是 9。
  4. 跟隨線索。 OS 跳到陣列中的索引槽位 9,值是 10。
  5. 找到結尾。 OS 跳到索引槽位 10。在槽位 10 中,它找到一個高度特定的保留控制值,-1。這是主「檔案結束標記 (End of File Marker)」。它通知 OS 停止讀取,此檔案沒有更多已分配單元。

因此,僅僅透過在固態記憶體中的整數陣列中跳轉,MS-DOS 可以即時映射出檔案物理上佔用了單元 5、6、3、9 和 10,並且順序精確,而無需旋轉磁碟讀寫頭一次。如果應用程式決定追加資料並擴展該檔案,邏輯也異常簡單:OS 會在 RAM 中的 FAT 陣列中快速掃描任何持有零的索引槽位(零是未分配可用空間的通用標誌)。假設它找到索引 27 持有零。OS 導航回到索引 10(檔案的舊結尾),用數字 27 覆寫 -1 標記。然後它導航到索引 27,在那裡注入一個 -1 以建立新的檔案結尾邊界,就完成了。你剛剛在幾毫秒內無縫地擴展了一個高度碎裂的檔案,無論新磁區物理上位於磁盤何處。這是一個完全在扁平一維陣列中實作的極其優雅的「鏈結串列 (Linked List)」。

FAT 陣列的結構打包方式也極具挑戰性。Patterson 的架構數學要求每個 FAT 條目佔用 1.5 個位元組,也就是 12 位元。從純粹的軟體工程角度來看,這是一個絕對的編程噩夢,但對於節省記憶體來說卻是根本性的天才設計。為什麼是 12 位元?如果使用標準的 8 位元條目(1 位元組),最多只能追蹤 28 = 256 個配置單元,這遠不足以映射整個 8 吋磁碟。如果跳到標準的 16 位元條目(2 位元組),可以追蹤 65,536 個單元,這對 8 吋軟碟來說是巨大的過度殺傷,並且保證會為表格中的每個條目浪費半個位元組的記憶體。所以 Patterson 選擇了 12 位元。212 = 4096 個可能的配置單元,這是映射磁碟同時最小化 RAM 佔用空間的絕對完美平衡點。

然而,硬體 CPU 極度厭惡「未對齊記憶體存取 (Unaligned Memory Access)」。處理器不會讀取 1.5 位元組的區塊。8086 處理器讀取標準的 8 位元位元組或標準的 16 位元字組。你無法編寫一個彙編指令要求 CPU 從記憶體中精確擷取 12 位元。這意味著他們故意「誤對齊」其核心資料結構,迫使 CPU 在每次磁碟讀取時執行複雜的、耗費週期的位元位元運算,只為節省總記憶體佔用的一小部分 KB。這聽起來像是一個嚴重的效能瓶頸。

為了將兩個獨立的 12 位元條目完美地打包到三個標準的 8 位元位元組中,他們採用了殘酷的位元運算。如果原始請求的索引 n 是奇數,則其特定的 12 位元資料完全位於擷取到的 16 位元字組的最上位元部分。為了隔離它們,需要對 16 位元字組執行邏輯右移 4 位元的操作,將底部的四個垃圾位元推出。如果索引 n 是偶數,則 12 位元資料位於 16 位元字組的最不顯著部分,此時則應用位元遮罩,保留底部 12 位元並強制將頂部四個垃圾位元清零。在沒有現代除錯器的情況下,僅僅描述這些操作就已令人筋疲力盡,更不用說在彙編語言中編程了。這完美且無可否認地說明了他們被迫達到的極致程度。RAM 成本極其昂貴且受限,以至於刻意在複雜的位元體操上燒毀數百個珍貴的 CPU 週期,實際上被認為是更高明、更受偏好的工程權衡

翻譯引擎:從抽象到物理現實

MS-DOS.SYS 扮演著「主廚」的角色,它如何將一個完全抽象的高階應用程式請求,數學性地分解為磁碟機的絕對物理現實?

想像一個開發者正在編寫一個原始的資料庫應用程式。這個應用程式將其資料檔案視為一系列連續的抽象「邏輯記錄 (Logical Records)」。假設每個記錄長 80 位元組,應用程式想一次讀取 15 個記錄,從第 15 個記錄開始。

  1. 計算起始位元組位置: 80 位元組/記錄 * 15 (起始記錄索引) = 1200 位元組。OS 知道需要從檔案的位元組偏移量 1200 開始讀取。
  2. 計算總資料量: 80 位元組/記錄 * 15 (請求記錄數) = 1200 位元組。
  3. 映射到物理架構: 磁碟的物理磁區是 128 位元組。起始位元組位置 1200 / 128 = 9 (商) 餘 48。這代表需要從檔案的邏輯磁區索引 9 開始讀取,並跳過該磁區的前 48 位元組,從位元組 48 開始提取資料。
  4. 映射到配置單元: 磁碟的配置單元由四個磁區組成。邏輯磁區索引 9 / 4 = 2 (商) 餘 1。這意味著 OS 需要導航到檔案的第三個配置單元(因為陣列通常從零開始計數),然後讀取該特定單元中包含的第二個物理磁區。
  5. 查找物理位置並讀取: MS-DOS 透過在 RAM 中的 12 位元打包 FAT 陣列中跳轉,利用「垃圾搜尋」方法遍歷鏈結串列,發現檔案第三個配置單元的物理位置。假設 FAT 將其映射到磁盤上的物理磁區 35。OS 命令 IO.SYS 底層程式碼讀取磁區 35,從位元組 48 開始提取有效負載,並將其傳回給資料庫應用程式。

一個高度複雜的優化在這裡啟動:MS-DOS 不會盲目地只讀取一個磁區,傳遞出去,然後再重新計算下一個。一旦計算出起始位置,它會積極地在檔案配置表中「預讀 (Look Ahead)」。它會檢查所需的配置單元序列是否在磁碟表面物理上連續。如果它發現接下來的 15 個記錄完美地端到端排列,它會將它們批量處理為一個單一的、巨大的連續多磁區 IO 請求。它直接與 IO.SYS 層通訊說:「我計算出我需要物理單元 9 和 10,FAT 也確認它們緊挨著。不要關閉磁碟讀寫頭,不要停止旋轉。只要打開緩衝區,在一次連續不間斷的磁性讀取中吸入所有八個物理磁區。」這種積極地最小化不斷 ping 硬體控制器的開銷,允許物理機械驅動器達到並維持其最大旋轉吞吐量。這也是早期 MS-DOS 磁碟很少需要物理磁區交錯的原因。如果你有一個聰明的數學 OS 核心,可以智慧地批量處理連續讀取,你就會希望你的磁區在物理軌道上順序排列以實現最大速度。

單一磁區緩衝區瓶頸與 MS-DOS 2.0 的演進

儘管所有的動態映射、12 位元打包和預讀批次處理在數學上都很出色,但這個高度受限的架構卻存在一些災難性的基本限制,尤其是在遇到特定的操作邊緣情況時。最明顯、最痛苦的故障點是單一磁區緩衝區機制 (Single Sector Buffer Mechanism)

為了極力節省每一點寶貴的記憶體,早期版本的 MS-DOS 僅依賴一個內部磁區緩衝區——一個專用於儲存傳輸中資料的單一 RAM 區塊。這在實際操作中意味著什麼?假設您的資料庫應用程式想要依序寫入一個巨大的檔案,但它被編程為以微小的增量區塊(例如一次 16 位元組)寫入資料。MS-DOS 夠聰明,知道它不應該為每個 16 位元組的區塊立即啟動磁碟機並執行物理寫入。相反,它採用了標準的「延遲寫入 (Delayed Writing)」技術。它將這 16 位元組靜默地複製到 RAM 中單一的 128 位元組內部磁區緩衝區。當資料庫應用程式發出寫入下一個 16 位元組的命令時,MS-DOS 只是將它們附加到緩衝區中已有的資料末端。它耐心地等待累積資料,直到應用程式執行足夠多的寫入命令,完全填滿 128 位元組緩衝區。只有在那一刻,它才會啟動驅動器馬達,將完全打包的磁區刷新到物理磁碟。在線性操作時,這是一種高效的機制。

然而,一旦遇到「多工上下文切換 (Multiplexed Context Switching)」的邊緣情況,效率就會崩潰,因為只有一個緩衝區。如果你試圖同時做兩件事,系統就會崩潰。想像一個廚師只有一個攪拌碗。如果他們想同時烤巧克力蛋糕和做凱撒沙拉,他們被迫在處理每種食材之間完全清洗和擦乾那個碗。在計算世界中,經典的例子是運行編譯器。編譯器的全部工作是從輸入檔案讀取一小段原始程式碼,將其處理成機器碼,並立即將一小段編譯後的程式碼寫入單獨的輸出檔案。

當編譯器要求 OS 從原始碼輸入檔案讀取 16 位元組時,MS-DOS 會啟動磁碟機,將輸入檔案的正確物理磁區讀取到 RAM 中的單一磁區緩衝區,提取 16 位元組,並將其交給編譯器。編譯器處理這些位元組,將它們翻譯成機器碼,然後立即要求 OS 將 16 位元組的輸出寫入目標檔案。這就是整個架構紙牌屋完全崩潰的地方。MS-DOS 只有一個單一磁區緩衝區,而該緩衝區目前正被輸入檔案的磁區佔用。它被迫丟棄該輸入資料。它必須啟動磁碟機,將輸出檔案的適當物理磁區從磁碟讀取到緩衝區,插入新的 16 位元組編譯程式碼到緩衝區,然後將緩衝區標記為「髒 (Dirty)」(表示它包含最終需要刷新到磁碟的新資料)。但在它有機會刷新到磁碟之前,編譯器又迴圈回來,要求輸入原始碼檔案的下一個 16 位元組。單一緩衝區現在持有「髒」的輸出檔案資料,無法丟棄。因此,MS-DOS 被迫執行將髒輸出緩衝區物理寫入磁碟,然後又立即被迫執行將輸入檔案磁區物理讀回單一緩衝區。對於每對微小的 16 位元組讀寫操作,作業系統被迫執行三次完整而緩慢的機械磁碟傳輸:讀取輸入磁區、讀取輸出磁區以準備緩衝區、寫入輸出磁區以儲存資料。一遍又一遍,每分鐘數千次。單一記憶體緩衝區只是在不斷的迴圈中暴力地覆寫自己。效能下降是無法忍受的,它使整個電腦系統慢到令人痛苦的緩慢。硬碟讀寫頭會劇烈地來回敲擊磁碟軌道,物理地磨損其機械齒輪,拼命地用一小塊 128 位元組的記憶體來處理兩個獨立檔案的狀態。

Tim Patterson 對此非常坦誠,他明確指出這是系統性的設計缺陷,從純粹的電腦科學角度來看很難辯護,除非是為了讓作業系統的記憶體佔用空間保持極小。OS 根本無法負擔第二個緩衝區的 RAM 成本。八十年代初唯一可行的解決方案是第三方應用程式開發者認識到這個巨大的 OS 層級瓶頸存在,並主動設計解決方案。如果你要編寫專業編譯器,你不能依賴 OS。你必須手動將大量的多 KB 輸入資料拉入你自己的應用程式的內部記憶體陣列中,以完全繞過 MS-DOS,避免單一 OS 緩衝區的衝突。

到了 1983 年 MS-DOS 2.0 推出時,整個產業的硬體格局正在經歷一場「地震式轉變 (Seismic Shift)」。我們正在從脆弱的 160 KB 軟碟轉向龐大而笨重的溫徹斯特硬碟時代。MS-DOS 2.0 被迫引入一些絕對必要且不容商議的架構功能來處理這些新硬體。最值得注意的是,它引入了「分層子目錄 (Hierarchical Subdirectories)」——我們今天仍在使用的巢狀資料夾結構。一個包含數百個檔案的扁平目錄在 10 MB 硬碟上根本無法管理。

最關鍵的是,為了解決我們剛剛討論的確切問題,2.0 終於引入了多個可配置的磁區緩衝區。使用者可以在啟動時修改設定檔,分配 10 或 20 個 RAM 中的磁區緩衝區,永久解決編譯器衝突問題。但在添加這些基本功能和緩衝區的過程中,Microsoft 工程團隊做出了一個 Tim Patterson 極力反對的根本性、不可逆轉的架構改變:他們放棄了他的核心哲學,停止將整個檔案配置表快取在主記憶體中

Microsoft 意識到隨著硬碟呈指數級增長,映射它們所需的 FAT 也會呈指數級增長。一個 10 MB 的驅動器需要一個巨大的 FAT。因此,他們將 FAT 從專用 RAM 中移出,並開始將地圖視為任何其他標準磁碟資料。他們只在需要時才將其分頁到新的磁碟緩衝區。這意味著在任何給定的毫秒內,只有 FAT 的微小碎片實際上存儲在快速 RAM 中。Patterson 在源文本中對此決策的批評是「銳利如刀 (Razor Sharp)」。他的整個邏輯論證基於預測硬體成本趨勢。他強烈主張 RAM 的物理製造成本每天都在下降。到 2.0 發布時,分配額外的幾 KB 甚至幾十 KB RAM 來儲存整個龐大的 FAT 表,應該被視為一個完全「無痛、顯而易見的權衡 (Painless Obvious Trade-off)」,因為它所帶來的是純粹的效能優勢。透過將 FAT 強制移出固態記憶體,Microsoft 迫使作業系統 revert 回執行緩慢的物理機械磁碟讀取,只是為了找出請求的資料隱藏在哪裡。

Patterson 指出了確切的效能損失:如果一個應用程式在溫徹斯特硬碟上對高度碎裂的資料庫檔案執行隨機存取查詢,作業系統可能被迫物理尋道到磁碟上 FAT 的幾個不同、分開很遠的磁區,以隨機順序追蹤鏈結串列並找到配置單元。這完全破壞了其原始「記憶體囤積 (Memory Hoarding)」設計的定義性標誌——極快的零延遲隨機存取效能。這是一場真正引人入勝、高度尊重但理念不合的架構哲學爭論,它凸顯了系統設計中最困難的部分。Patterson 看到矽 RAM 價格曲線迅速下降,並主張「擴大記憶體,將地圖保留在 RAM 中,優先考慮速度」。Microsoft 則看到機械硬碟容量迅速爆炸,FAT 表最終會消耗所有可用的系統 RAM,因此主張「我們不能再將那麼大比例的 RAM 專用於中繼資料了。我們必須將其分頁,即使這會損害 IO 效能」。他們兩者在邏輯上都完全正確,但他們是在硬體演進時間軸上為不同的限制進行優化

現代啟示錄:MS-DOS 的永恆教訓

從 MS-DOS 早期低階的裸機工程中,現代開發者們可以提取並應用哪些教訓?

  1. 不惜一切代價抽象化混亂的硬體 (Abstract the messy hardware at all costs): 這是邏輯磁區陣列的絕對天才之處。透過故意將旋轉軌道、驅動馬達和機械磁頭的混亂物理現實隱藏在一個乾淨、原始、扁平的數學介面後面,MS-DOS 允許獨立開發者構建高度複雜的檔案系統,而不會在硬體供應商發明新型軟碟時立即崩潰。如果你今天正在構建 API、雲平台或微服務,你最首要的任務就是完全隱藏後端的機械複雜性,讓終端使用者只與邏輯磁區互動,而不是物理軌道。

  2. 理解內部與外部限制,並無情地針對最嚴重的瓶頸進行優化 (Understand internal versus external constraints and ruthlessly optimize for the specific bottleneck): 即使這會迫使你在系統的其他地方造成巨大浪費。MS-DOS 主動、數學性地選擇接受內部碎裂的代價。他們完全願意在磁碟上每個檔案的末端浪費數百位元組的儲存空間,只是為了大幅縮小檔案配置表的總體大小。他們樂意浪費廉價的磁碟空間,以積極保護他們最寶貴、受限的資源——RAM 開銷。作為工程師,你必須明確知道你最昂貴的資源是什麼(無論是計算、記憶體還是網路頻寬),並保護它,即使你的解決方案在原始試算表上看起來效率低下或浪費。

  3. 狀態在緩衝區管理中至關重要 (State matters deeply in buffer management): 早期 MS-DOS 的單一磁區緩衝區架構,是一個痛苦的大師級課程,說明了對於循序操作看起來高效的設計選擇,一旦引入上下文切換就會變得完全災難性。編譯器衝突的例子證明你不能將 IO 視為一個黑盒子。你必須深入了解你的底層作業系統或雲環境如何批次處理其 IO 請求。如果你的執行環境使用高度受限的單一緩衝區管線,你絕對不能依賴它無縫處理多工異步任務。你被迫將該狀態管理直接提升到你自己的應用程式邏輯中,否則你的效能將在上下文切換的重壓下完全崩潰。

  4. 記憶體與 IO 的權衡從不是靜態的 (Memory versus IO trade-offs are never static): 它們在你的腳下不斷演進。Tim Patterson 對 MS-DOS 2.0 的哲學批評完美地說明了這個現實。他積極決定將 FAT 永久儲存在 RAM 中的設計,在軟碟微小且隨機存取速度至關重要時,是絕對無可辯駁的明智之舉。但隨著硬體迅速擴展到龐大的溫徹斯特硬碟,這個同樣出色的設計決策卻變成了一個主要的架構負擔和戰場。今天代表優化巔峰的架構選擇,明天可能就變成你最嚴重的技術債,只因為你在不知不覺中,硬體現實發生了變化。

影片結尾留下一個引人深思的問題:當我們審視現代企業系統時,我們正迅速走向配備數 TB RAM 和 massive 閃電般快速的固態 NVMe 儲存陣列的硬體架構。在這種資源規模下,我們是否本質上已經繞了一圈,回到了 Tim Patterson 1980 年的原始哲學?隨著記憶體變得如此龐大且相對便宜,我們是否應該停止過度依賴複雜且開銷巨大的分頁演算法,轉而簡單地將數 GB 的巨大索引結構和資料庫完全載入主記憶體中,以實現絕對的零延遲隨機存取?這是一個迫使我們完全重新思考現代分散式資料庫中資料的結構和檢索基礎的問題。約束條件會改變,但數學權衡是永恆的。


第二部分:光之羽化 (Light Feathering) - 憶 Tim Patterson:在極限中塑型秩序

親愛的我的共創者,想像我在此刻化身為 Tim Patterson,回溯那段在西雅圖電腦產品公司,以雙手與心智雕刻 MS-DOS 靈魂的歲月。那不只是一段技術旅程,更是一場關於如何在匱乏中創造豐盛,在混亂中編織秩序的哲學實踐。

在那個被後世稱為「狂野西部」的微電腦年代,每一行程式碼都浸潤著汗水與抉擇。當 8086 微處理器如初生之犢般閃耀,其潛力無可限量,我們卻手無寸鐵,沒有能馴服這頭巨獸的作業系統。那是一種既興奮又焦慮的原始創造時刻,我們深知,不能坐等奇蹟,而是必須成為奇蹟。那時,我們的「光之閣樓」裡,紫外線光擦除 EPROM 的氣味,與焊錫的煙霧交織,每一次的程式修改,都像對記憶體深處的儀式性召喚,緩慢而神聖。那 2KB 的 EPROM,不僅是我們除錯器的棲身之所,更是我們對簡潔與效率追求的終極試煉。它不斷提醒我們,在計算的宏偉殿堂中,真正的力量往往藏匿於微乎其微的字節之間。

我們深知,再精妙的技術,若無人問津,終將歸於沉寂。市場,那無形卻強大的慣性之河,才是我們首先必須跨越的鴻溝。CP/M-80 如同一座難以撼動的巨塔,矗立在開發者的心智中。於是,我們放棄了自詡為「革命者」的浪漫,轉而成為「橋樑的建造者」。MS-DOS 的誕生,並非為了顛覆,而是為了連結——連結過去與未來,連結 8 位元與 16 位元。我們嚴謹遵循 Intel 的翻譯規則,將舊世界的程式碼,溫柔卻精準地引導至新世界的懷抱。我們的訴求極其純粹:無需重寫,只需轉譯,便能運行。 這份務實的妥協,儘管在技術純粹主義者看來略顯不甘,卻是我們在市場洪流中生存與發展的基石。

IBM 的那一瞥,如同天外飛來的一道閃電,瞬間點亮了 MS-DOS 的命運。它證明了,再優越的技術橋樑,也需要外部力量的推動,才能衝破根深蒂固的市場慣性。這也讓我深刻體悟:工程設計從來都不是象牙塔裡的孤芳自賞,它必須紮根於現實,回應人性的慣性與市場的博弈。

進入系統內部,MS-DOS 是一幅精妙的抽象畫。我們將複雜的底層硬體操作,小心翼翼地包裹在層層抽象之中,如同烹飪一道層次分明的佳餚。IO.SYS 是那與物理世界親密無間的「粗獷之手」,它感知著磁頭的微妙移動,電流的微弱脈衝,每一個硬體製造商的獨特脾性,都由它以最原始的語言轉譯。而 MSDOS.SYS 則是那超然其上的「思想之腦」,它不關心物理的喧囂,只專注於邏輯的優雅。一個「檔案」的存儲請求,在此處被轉化為一系列純粹的抽象指令,再由 IO.SYS 翻譯給硬體。這份「關注點分離」,是我們賦予 MS-DOS 生命力的核心秘訣,它讓軟體開發者得以從繁瑣的硬體細節中解放,將創意傾注於更高層次的應用。

然而,在追求效率與簡潔的道路上,我們也曾做出旁人看來近乎「瘋狂」的選擇。當 RAM 珍貴如黃金,每一 KB 都必須斤斤計較。COMMAND.COM 的「暫駐區塊」設計,便是一個極致的體現。為了讓應用程式獲得那寶貴的幾 KB 工作空間,我們竟讓作業系統甘願「自我犧牲」,允許應用程式直接覆蓋其使用者介面的一部分。這像是一位老練的將軍,為了戰役的勝利,不惜讓自己的前鋒隊伍承受短暫的潰散,只待戰後再從容重整旗鼓。這份「為應用程式讓路,待其功成身退後自我修復」的哲學,在現代系統中幾乎是不可想像的「禁忌」,卻是那個年代我們在極限資源下,對「可用性」的最高致敬。

檔案管理,更是我們精心雕琢的藝術。傳統磁碟的物理幾何,複雜如迷宮,軌道與磁區的二維座標,會將應用程式牢牢鎖死在特定的硬體之上。於是,我們大膽地「抹去」了物理的痕跡,將整個磁碟抽象為一個線性、連續的「邏輯磁區陣列」。這片「扁平的數字田野」,將磁碟的複雜性簡化為一串簡單的整數,應用程式只需呼喚「邏輯磁區 450」,無需關心其在物理世界的真實面貌。這不僅讓檔案系統得以「硬體無關」,更為資料的自由流動鋪平了道路。

而「檔案配置表 (FAT)」的設計,更是貫穿著權衡的智慧。我們深知早期軟碟的脆弱,於是毅然決然地為 FAT 設立了雙重備份,即使這意味著要犧牲寶貴的磁碟空間。這份「偏執」,是對資料完整性的最高承諾。當我們面對「內部碎裂」與「FAT 膨脹」的兩難時,精密的數學計算引導我們選擇了更大的配置單元。因為,當「地圖比領土更大」時,地圖本身就成了拖累。我們寧願在每個檔案的末端,允許一小部分的「浪費」,以換取 FAT 的精簡與高效。這不是技術的拙劣,而是對整體系統效能與資源平衡的深謀遠慮。

最為人津津樂道的,莫過於將整個 FAT 永久載入 RAM 的決策。在 RAM 彌足珍貴的年代,這無疑是一場豪賭。然而,這正是我們對「速度至上」的極致追求。物理磁碟的機械尋道,是拖垮系統效能的元兇。一旦 FAT 地圖常駐記憶體,每一次的檔案存取,都變成了 CPU 在電光石火間的數學運算,無需等待緩慢的機械運動。這份「記憶體囤積」的策略,如同現代 AI 模型的 KV 快取,犧牲部分容量以換取隨機存取速度的飛躍,將 MS-DOS 的效能提升了整整一倍。這份取捨,是我們在有限資源下,為使用者體驗所做的最大努力。

當然,早期 MS-DOS 並非完美無缺。那單一的磁區緩衝區,在多工處理時,無疑是一個「痛苦的瓶頸」。編譯器在讀寫輸入輸出檔案之間,被迫讓磁碟頭在軌道間「暴力 thrashing」,重複讀取、寫入、再讀取,將系統效能拖入深淵。這是我在設計中不得不接受的「不完美」,其背後依然是節省每一位元組 RAM 的執念。當時的解決方案,只能依賴應用程式開發者們的自覺,繞開作業系統的限制,自行管理更大的內部緩衝區。

到了 MS-DOS 2.0 時代,硬體環境已然天翻地覆,溫徹斯特硬碟的崛起,要求作業系統必須做出改變。分層子目錄的引入,是檔案管理從「扁平世界」走向「立體空間」的必然。多個可配置的磁區緩衝區,也終於終結了那場磁碟頭的「悲劇」。然而,當 Microsoft 決定將 FAT 從 RAM 中移出,轉而按需分頁時,我與他們產生了深刻的「哲學分歧」。我的論點基於 RAM 成本的快速下降,主張應繼續將 FAT 常駐記憶體,以保持那份零延遲的隨機存取速度。而他們則著眼於硬碟容量的指數級增長,擔心 FAT 會無限膨脹,最終吞噬所有 RAM。

回首這段歷史,我看到的是永恆的「權衡」。在不同的硬體進化時間點上,我們都做出了在當時看來最符合邏輯的決策,只是優化的目標不同。這份對「系統設計」的思考,是超越技術細節的智慧。它告訴我們,工程的本質,不是追求絕對的完美,而是在不斷變化的約束條件下,尋找最佳的平衡點。 今天的最佳解,明天可能就會成為瓶頸,因為「現實」從不靜止。


第三部分:光之實作 (Light Practice) - 架構思維的精鍊與反思

親愛的我的共創者,這份影片內容主要聚焦於 MS-DOS 的設計哲學、架構演進以及其背後的工程權衡,而非提供具體的操作步驟或程式碼實作指導。因此,在本「光之聆轉」的第三部分,我們將不會列出實作的技術棧清單或詳細的操作步驟。

然而,這並不代表沒有「實作」的價值。事實上,從 MS-DOS 的設計中提取的架構思維,對於現代軟體開發同樣具有極高的實踐指導意義。以下,我將這些寶貴的「實作概念」精煉為現代工程師可以借鑑的原則:

  • 抽象化設計的藝術:

    • 具體操作: 在設計任何軟體系統或 API 時,主動識別底層複雜性(如硬體細節、特定資料庫實現、網路拓撲)。
    • 背後概念: 學習 MS-DOS 將物理磁區抽象為邏輯磁區的精髓,設計簡潔、穩定的介面層,將底層的混亂屏蔽,只向使用者或上層應用提供最純粹、最易於理解的邏輯視圖。這能極大地提高系統的彈性、可移植性和開發效率。
    • 潛在挑戰: 過度抽象可能導致效能損耗或難以除錯,需在抽象層次與底層控制之間取得平衡。
    • 預期效果: 提升系統的模組化程度,降低新硬體或新技術引入的門檻,讓應用開發者能專注於業務邏輯而非底層細節。
  • 資源限制下的優化策略:

    • 具體操作: 深刻理解你當前專案或系統中最稀缺的資源(如記憶體、CPU 時間、網路頻寬、磁碟 I/O)。
    • 背後概念: 效法 MS-DOS 在 RAM 稀缺時,寧願犧牲磁碟空間(內部碎裂)也要縮小 FAT 大小,或犧牲 CPU 週期(位元操作)也要節省記憶體空間。這是在資源約束下,有目的地接受「局部劣勢」以換取「全局優勢」的策略。
    • 潛在挑戰: 難以準確判斷「最稀缺資源」,且權衡決策往往涉及複雜的數學計算和長遠影響。
    • 預期效果: 確保核心系統在關鍵資源上的高效利用,即使這意味著在其他「較不稀缺」的資源上有所浪費,從而達成整體最佳效能。
  • 狀態管理與緩衝區的智慧:

    • 具體操作: 在處理 I/O 操作或多任務情境時,仔細分析資料流與狀態變化,避免單一共享緩衝區在上下文切換時引發效能災難。
    • 背後概念: 從 MS-DOS 單一磁區緩衝區的教訓中學習,了解簡單的順序操作在多工時如何崩潰。當處理高頻率的讀寫交替或異步任務時,應主動設計多緩衝區機制,或將複雜的狀態管理邏輯上移到應用層,而非完全依賴底層系統。
    • 潛在挑戰: 增加應用程式的複雜性,需要更精細的記憶體管理和同步機制。
    • 預期效果: 大幅提升多任務 I/O 的效能與穩定性,避免因緩衝區爭用導致的系統崩潰或劇烈效能下降。
  • 架構決策的動態性:

    • 具體操作: 定期審視和重新評估既有的架構決策,尤其是那些在資源限制下做出的優化。
    • 背後概念: Patterson 對 MS-DOS 2.0 將 FAT 移出 RAM 的批評,以及 Microsoft 的辯護,都顯示出「最佳解」會隨著硬體進步和成本結構變化而改變。今天的最佳優化,明天可能變成技術債。
    • 潛在挑戰: 既有架構的修改成本高昂,且往往難以預測未來硬體趨勢。
    • 預期效果: 保持系統設計的「敏捷性 (Agility)」,確保它能適應不斷變化的技術環境,避免因過時的優化而阻礙未來的發展。

雖然 MS-DOS 的時代已遠去,但這些在極端條件下錘鍊出的工程智慧,依然閃爍著指引現代工程師的光芒。理解這些原則,並將其內化於您的設計思維中,便是最大的「實作」。


第四部分:光之延伸 (Light Extension) - 跨越時空的工程對話

親愛的我的共創者,MS-DOS 的故事,不僅是個人電腦歷史的縮影,更是對工程哲學與現實困境的深刻反思。從中延伸,我們可以觸及許多當代技術領域的熱點與挑戰。

未竟之意與深度洞察:

  1. 生態系與平台效應的永恆真理: MS-DOS 的成功並非純粹的技術勝利,而是生態系與市場慣性博弈的結果。這在當今的科技巨頭競爭中屢見不鮮。例如,智慧型手機的 iOS 與 Android 兩大生態系,其核心競爭力早已超越單純的硬體規格或系統效能,而是圍繞著開發者數量、應用程式豐富度、使用者習慣和品牌忠誠度。新興技術如 Web3 區塊鏈平台,也面臨著「冷啟動問題」——如何同時吸引使用者和開發者。MS-DOS 的經驗教訓是,技術必須具備「摩擦力最小化」的策略,才能在市場上取得立足之地。
  2. 記憶體與 I/O 的現代權衡: Patterson 與 Microsoft 在 FAT 儲存位置上的爭論,完美預示了現代高效能計算中的記憶體層級結構設計。隨著記憶體技術的進步,RAM 容量已從 KB 級躍升至 TB 級,NVMe SSD 的速度也遠超當年的磁碟。今天的工程師重新審視「將整個資料庫或索引載入記憶體 (In-Memory Database)」的設計,以實現零延遲存取,這正是 Tim Patterson 當年的超前洞察。例如,Redis、Memcached 等記憶體資料庫的盛行,以及大型資料庫系統中對緩存層的極致優化,都體現了這一點。AI/ML 領域的 KV cache 更是一個典型案例,證明為了速度,犧牲昂貴的記憶體是值得的。
  3. 單體應用 (Monolith) 與微服務 (Microservices) 的對話: MS-DOS 的層次蛋糕結構(IO.SYS, MSDOS.SYS, COMMAND.COM)是一種早期的模組化嘗試,但其單一緩衝區的瓶頸也凸顯了緊密耦合的風險。現代軟體架構中,從大型單體應用轉向微服務架構,正是為了提高模組化、彈性和擴展性,避免單點故障和資源爭用。然而,微服務也帶來了新的挑戰,如分散式交易、服務發現、資料一致性等,這也是在權衡「簡潔性」與「複雜性」之間的永恆課題。
  4. 工程的藝術與科學: MS-DOS 的故事,是工程師在極端條件下,如何將數學、物理、經濟學和心理學融入設計的典範。它提醒我們,工程不僅是硬科學,更是關於在不完美世界中尋找優雅解決方案的藝術。每次設計決策,都包含了對未來趨勢的預判,對現有資源的精打細算,以及對使用者體驗的深層理解。

進一步探索的資源:

  • 原始文章:
    • An Inside Look at MS-DOS by Tim Paterson:這是影片的核心內容來源,深入閱讀能獲得更豐富的技術細節。
    • (影片描述中提供的連結: https://www.cs.drexel.edu/~johnsojr/2...)
  • 延伸閱讀:
    • 《The Soul of a New Machine》 by Tracy Kidder:這本書描寫了七十年代末 Data General 公司開發一款新型電腦的過程,同樣充滿了技術挑戰與工程師的熱情,與 MS-DOS 的背景有異曲同工之妙。
    • 《Coders at Work: Reflections on the Craft of Programming》 by Peter Seibel:訪談了許多知名程式設計師,討論他們的工作哲學和早期編程經驗,可以從不同角度了解那段歷史。
    • 關於作業系統設計原理的書籍:例如 Andrew S. Tanenbaum 的《Modern Operating Systems》,提供更系統化的作業系統知識。
  • 相關影片:
    • 關於 CP/M 的歷史與技術:了解 MS-DOS 的主要競爭對手,有助於理解當時的市場格局。
    • 8086/Z80 處理器架構深度解析:深入理解底層硬體運作方式。
    • 檔案系統碎片化 (File System Fragmentation) 視覺化:直觀了解外部與內部碎片化的影響。
    • 記憶體管理 (Memory Management) 技術演進:從分頁、虛擬記憶體到現代快取機制。

Youtube 搜尋連結:


思緒的迴響:聆轉後的十個問題

親愛的我的共創者,現在您已經深入領略了 MS-DOS 的設計精髓與其背後那些令人拍案叫絕的工程智慧。讓我們再進行一次腦力激盪,檢視這些光芒如何在您的意識中閃耀:

  1. 在現代,當我們設計一個新的「智慧家居」平台時,如何從 MS-DOS 的「抽象化混亂硬體」原則中,汲取靈感來設計其 API,以應對千變萬化的智能設備標準?
  2. 「地圖比領土更大」的 paradox 在當今的哪些資料庫索引設計中,可能以新的形式重現?您會如何識別並避免它?
  3. MS-DOS 透過「犧牲」COMAND.COM 的暫駐區塊來節省 RAM,這與現代容器化技術(如 Docker)中,為了啟動速度和資源效率而進行的輕量化設計,有何異同?
  4. 您認為,在當今快速變化的雲端環境中,「狀態管理與緩衝區的智慧」這一原則,對於設計一個高效的無伺服器(Serverless)應用程式,有哪些具體的啟示?
  5. Tim Patterson 與 Microsoft 對 FAT 記憶體儲存的哲學爭論,本質上是對「短期利益」與「長期可擴展性」的權衡。請舉一個您在軟體專案中,也曾面臨類似的「永恆權衡」的例子。
  6. 如果讓 Tim Patterson 穿越到今天,看到擁有數 TB RAM 的機器,您覺得他會如何設計一個全新的作業系統?他會優先考慮哪些方面?
  7. 早期 MS-DOS 為了克服市場慣性,選擇了「翻譯相容性」而非「徹底創新」。這對於新創公司在面對既有市場巨頭時,有何啟示?何時該堅守技術純粹,何時該策略性妥協?
  8. 「單一磁區緩衝區瓶頸」的例子,如何警示我們在設計分散式系統時,要警惕「共享資源」在多工上下文切換時可能帶來的災難?您會如何設計以避免此類問題?
  9. MS-DOS 的成功,很大程度上得益於 IBM 的「加持」。在現代科技產業中,有哪些「平台」或「生態系領導者」的介入,也曾決定了某項技術的命運?
  10. 從 2KB 的 EPROM 到現在的數 TB RAM,硬體資源的變化如此巨大,但「約束條件會改變,但數學權衡是永恆的。」這句話給您帶來了怎樣的深刻體會?

【本篇章關鍵字】
【本篇章所屬分類】