01 / 導讀
導讀
引用
Bryant, R. E., & O'Hallaron, D. R. (2015). Computer Systems: A Programmer's Perspective (3rd ed.). Pearson.
章節概要
全書分三部分共十二章,另有一個關於錯誤處理的簡短附錄。作者明確說明了取捨標準:只有當某個主題會影響使用者級 C 程式的效能、正確性或實用性時才收入書中。各章末尾有小結和參考文獻說明,多數章還有習題,書中練習題的解答集中放在每章末尾。
第一部分:程式結構和執行(第 1–6 章)
第 1 章:A Tour of Computer Systems(電腦系統漫遊)
本章沿著一個簡單的「hello, world」程式的生命週期,引出主要主題:資訊就是位加上上下文、編譯系統對程式的翻譯、執行程式的硬體組成、快取與儲存層次、作業系統的行程、執行緒、虛擬記憶體和檔案,以及透過網路通訊。章末給出三個反覆出現的主題:Amdahl 定律、並行與並行,以及抽象。
第 2 章:Representing and Manipulating Information(資訊的表示和處理)
本章涵蓋資訊儲存(十六進位制、字長、位元組順序、C 中的位級運算和邏輯運算)、整數表示(無符號和二補數編碼、轉換、符號擴充套件與截斷)、整數運算和浮點數(IEEE 表示、舍入、C 中的浮點數)。作者強調這些內容對程式設計師的影響,例如兩個正數相加可能得到負數。他們指出,讀者最常覺得這一章吃力;第三版標出了講法轉向數學化的地方,以便讀者先略讀一遍。
第 3 章:Machine-Level Representation of Programs(程式的機器級表示)
讀者在這裡學習閱讀 C 編譯器生成的 x86-64 程式碼:資料傳送和算術運算、條件碼、跳轉、迴圈與 switch 語句、程式與執行時堆疊、陣列、結構與聯合、對齊、指標、使用 gdb 除錯器、緩衝區溢位及其防禦,以及浮點程式碼。
第 4 章:Processor Architecture(處理器架構)
本章圍繞 Y86-64 指令集設計一個簡化的處理器。它介紹邏輯設計和硬體控制語言 HCL,分階段構建順序實作,解釋管線化的原理與侷限,並行展出一個五級管線化實作,涉及冒險、例外處理、控制邏輯和效能分析。
第 5 章:Optimizing Program Performance(最佳化程式效能)
本章先講最佳化編譯器能做什麼、不能做什麼,然後消除迴圈低效、冗餘的程式呼叫和不必要的記憶體引用。在介紹了現代亂序處理器如何工作的模型之後,講迴圈展開、多累加器和重新結合,暫存器溢位和分支預測錯誤等限制因素,記憶體效能,以及效能剖析。
第 6 章:The Memory Hierarchy(記憶體層次結構)
本章涵蓋儲存技術(RAM、磁碟、固態硬碟)、區域性、記憶體層次結構,以及快取記憶體(直接對映、組相聯和全相聯快取、寫操作、快取引數對效能的影響)。最後講編寫快取友好的程式碼,以及從「記憶體山」角度看效能。
第二部分:在系統上執行程式(第 7–9 章)
第 7 章:Linking(連結)
第 7 章涵蓋編譯器驅動程式、靜態連結、目的檔、符號與符號解析、重定位、可執行檔與載入、使用共用函式庫的動態連結、位置無關程式碼、函式庫打樁,以及操作目的檔的工具。
第 8 章:Exceptional Control Flow(例外控制流程)
本章介紹例外、行程、行程控制、訊號和非本地跳轉。作者說,讀完這一章,讀者就能寫出帶作業控制的簡單 Unix shell。
第 9 章:Virtual Memory(虛擬記憶體)
本章講解實體定址與虛擬定址、作為快取工具的虛擬記憶體、記憶體管理與保護、位址轉譯、Intel Core i7 與 Linux 記憶體系統的案例研究、記憶體對映、動態記憶體分配、垃圾收集,以及 C 程式中常見的與記憶體有關的錯誤。
第三部分:程式間的互動和通訊(第 10–12 章)
第 10 章:System-Level I/O(系統級 I/O)
本章涵蓋 Unix I/O、檔案、開啟、讀寫、處理「不足值」的穩健 I/O 包、檔案元資料、目錄、檔案共享、I/O 重定向和標準 I/O,為後兩章做準備。
第 11 章:Network Programming(網路程式設計)
本章介紹使用者端-伺服器模型、網路與全球 IP 網際網路、通訊端介面、Web 伺服器,以及一個 Tiny Web 伺服器。作者稱之為切入網路程式設計的一個薄片,目標是做出一個簡單的 Web 伺服器。
第 12 章:Concurrent Programming(並行程式設計)
最後一章比較基於行程、基於 I/O 多路複用和基於執行緒的並行,然後講共享變數、用號誌同步、用執行緒實作並行,以及其他問題:執行緒安全、可重入性、競爭和死鎖。
附錄 A:Error Handling(錯誤處理)
關於 Unix 系統中的錯誤處理和錯誤處理包裝函式的簡短附錄。
核心概念
第一部分:程式結構和執行(第 1–6 章)
- 二補數和 IEEE 浮點表示:為什麼有限的位元模式會給出令人意外的算術結果。
- 機器級程式碼與執行時堆疊:C 語言結構和程式如何對應到指令。
- 管線化:讓指令的各階段重疊執行,以及限制它的冒險。
- 區域性與記憶體層次結構:為什麼決定效能的是存取模式,而不僅是處理器速度。
第二部分:在系統上執行程式(第 7–9 章)
- 連結與重定位:目的檔和函式庫如何變成可執行檔。
- 例外控制流程:例外、訊號和行程是並行的來源。
- 虛擬記憶體與動態分配:位址轉譯,以及 malloc 和 free 的實作。
第三部分:程式間的互動和通訊(第 10–12 章)
- Unix I/O 與通訊端:網路程式的基本構件。
- 並行伺服器:比較行程、I/O 多路複用和執行緒。
- 同步:號誌、競爭和死鎖。
評析
優點
- 清晰的組織思想。 作者把「構建者視角」與程式設計師視角相對照,並對每個主題應用同一條取捨標準,所以連結、訊號和 malloc 被收入書中,而加法器或匯流排的詳細設計被略去。
- 主動學習融入書中。 新概念之後緊跟練習題,解答在每章末尾;習題標有工作量等級,從幾分鐘到十小時的實驗不等。所有程式碼示例都在 Linux 上編譯執行過,源程式碼可從本書網站獲得。
- 來自長期開設課程的實驗。 前言介紹了與本書配套的實驗:資料實驗、二進位制炸彈、緩衝區溢位、架構、效能或快取、shell、malloc 和代理實驗。供自學使用、不含答案的版本可在作者網站上獲得。
- 對 C 語言新手的支援。 「New to C?」提示指出語言方面的要點,網路附註(web aside)把補充材料移出正文。
- 使用靈活。 前言把各章對映到五種課程型別,從電腦組成課程到系統程式設計課程。
侷限
- 繫結單一平臺。 本書面向 x86-64 機器程式碼、gcc 編譯器和 Linux。使用其他指令集的讀者看到的機器程式碼會不同,不過作者稱整體行為應當一致。
- 需要 C 語言基礎。 作者假定讀者熟悉 C 或 C++;只會 Java 的讀者需要多花力氣,只會 Python、Ruby 或 Perl 的讀者則被建議先學 C。
- 簡化的處理器。 第 4 章為講解管線化設計了 Y86-64 處理器,它是 x86-64 的精簡子集,是教學用設計,而不是商用處理器的模型。
- 有意為之的取捨。 作者把網路程式設計一章稱為一個薄片,而取捨標準也排除了加法器設計這類硬體主題。
- 硬體示例較舊。 本版出自 2015 年,處理器和快取示例反映的是當時的機器。
在課程中的定位
《Computer Systems: A Programmer's Perspective》從軟體一側審視機器。Petzold 的 Code 是面向普通讀者的敘述性入門,Nisan 和 Schocken 的 The Elements of Computing Systems 以專案方式從邏輯閘起步搭建一臺電腦;兩者都可以排在本書之前。Harris 和 Harris 的 Digital Design and Computer Architecture, RISC-V Edition 自硬體向上講,並讓學生自己設計處理器,因此可與本書第 4 章搭配。研究生層次的架構定量研究,則放在之後:Hennessy 和 Patterson 的 Computer Architecture: A Quantitative Approach,以及 Shen 和 Lipasti 的 Modern Processor Design,後者詳細講述第 5 章只用模型概略描述的亂序超標量處理器。
如何使用本書
本書面向能用 C 或 C++ 程式設計、想弄清自己的程式底層發生了什麼的電腦和工程專業學生。不要求具備硬體或組合語言經驗。
依據前言中的課程型別,實用的安排如下:
- 面向程式設計師的課程核心: 第 1 至 3 章和第 5 至 9 章,從資料表示一路講到機器程式碼、最佳化、記憶體層次結構、連結、行程和虛擬記憶體。
- 系統程式設計課程再加: 第 10 至 12 章,一步步構建出一個並行 Web 伺服器。
- 電腦組成課程再加: 第 4 章處理器架構。
- 練習: 每個概念出現時就做練習題,並嘗試做實驗,尤其是資料、炸彈、緩衝區溢位、快取、shell 和 malloc 實驗,手邊備好 Linux 機器或虛擬機器。
