關(guān)于我們
書單推薦
新書推薦
|
深入理解計(jì)算機(jī)系統(tǒng)(英文版·第3版)
本書是一本將計(jì)算機(jī)軟件和硬件理論結(jié)合講述的經(jīng)典教材,內(nèi)容涵蓋計(jì)算機(jī)導(dǎo)論、體系結(jié)構(gòu)和處理器設(shè)計(jì)等多門課程。本書*大的特點(diǎn)是為程序員描述計(jì)算機(jī)系統(tǒng)的實(shí)現(xiàn)細(xì)節(jié),通過描述程序是如何映射到系統(tǒng)上,以及程序是如何執(zhí)行的,使讀者更好地理解程序的行為,找到程序效率低下的原因。
和第2版相比,本版內(nèi)容上*大的變化是,從以IA32和x86-64為基礎(chǔ)轉(zhuǎn)變?yōu)橥耆詘86-64為基礎(chǔ)。主要更新如下: ·基于x86-64,大量地重寫代碼,首次介紹對處理浮點(diǎn)數(shù)據(jù)的程序的機(jī)器級支持。 ·處理器體系結(jié)構(gòu)修改為支持64位字和操作的設(shè)計(jì)。 ·引入更多的功能單元和更復(fù)雜的控制邏輯,使基于程序數(shù)據(jù)流表示的程序性能模型預(yù)測更加可靠。 ·擴(kuò)充關(guān)于用GOT和PLT創(chuàng)建與位置無關(guān)代碼的討論,描述了更加強(qiáng)大的鏈接技術(shù)(比如庫打樁)。 ·增加了對信號處理程序更細(xì)致的描述,包括異步信號安全的函數(shù)等。 ·采用*新函數(shù),更新了與協(xié)議無關(guān)和線程安全的網(wǎng)絡(luò)編程。 【特別說明:原出版社授權(quán)影印版權(quán)時(shí),明確規(guī)定不能加參考文獻(xiàn)和索引,前言及目錄也要翻譯為中文,因此本書影印版與原書仍然有所不同】
英文原版,原汁原味。影印版采用雙色精裝印制工藝,提供更加良好的閱讀體驗(yàn)
【注:根據(jù)原出版社要求,影印版刪去了參考文獻(xiàn)部分!
本書(簡稱CS:APP)的主要讀者是計(jì)算機(jī)科學(xué)家、計(jì)算機(jī)工程師,以及那些想通過學(xué)習(xí)計(jì)算機(jī)系統(tǒng)的內(nèi)在運(yùn)作而能夠?qū)懗龈贸绦虻娜恕?nbsp;
我們的目的是解釋所有計(jì)算機(jī)系統(tǒng)的本質(zhì)概念,并向你展示這些概念是如何實(shí)實(shí)在在地影響應(yīng)用程序的正確性、性能和實(shí)用性的。其他的系統(tǒng)類書籍都是從構(gòu)建者的角度來寫的,講述如何實(shí)現(xiàn)硬件或系統(tǒng)軟件,包括操作系統(tǒng)、編譯器和網(wǎng)絡(luò)接口。而本書是從程序員的角度來寫的,講述應(yīng)用程序員如何能夠利用系統(tǒng)知識來編寫出更好的程序。當(dāng)然,學(xué)習(xí)一個(gè)計(jì)算機(jī)系統(tǒng)應(yīng)該做些什么,是學(xué)習(xí)如何構(gòu)建一個(gè)計(jì)算機(jī)系統(tǒng)的很好的出發(fā)點(diǎn),所以,對于希望繼續(xù)學(xué)習(xí)系統(tǒng)軟硬件實(shí)現(xiàn)的人來說,本書也是一本很有價(jià)值的介紹性讀物。大多數(shù)系統(tǒng)書籍還傾向于重點(diǎn)關(guān)注系統(tǒng)的某一個(gè)方面,比如:硬件架構(gòu)、操作系統(tǒng)、編譯器或者網(wǎng)絡(luò)。本書則以程序員的視角統(tǒng)一覆蓋了上述所有方面的內(nèi)容。
如果你研究和領(lǐng)會了這本書里的概念,你將開始成為極少數(shù)的“牛人”,這些“牛人”知道事情是如何運(yùn)作的,也知道當(dāng)事情出現(xiàn)故障時(shí)如何修復(fù)。你寫的程序?qū)⒛軌蚋玫乩貌僮飨到y(tǒng)和系統(tǒng)軟件提供的功能,對各種操作條件和運(yùn)行時(shí)參數(shù)都能正確操作,運(yùn)行起來更快,并能避免出現(xiàn)使程序容易受到網(wǎng)絡(luò)攻擊的缺陷。同時(shí),你也要做好更深入探究的準(zhǔn)備,研究像編譯器、計(jì)算機(jī)體系結(jié)構(gòu)、操作系統(tǒng)、嵌入式系統(tǒng)、網(wǎng)絡(luò)互聯(lián)和網(wǎng)絡(luò)安全這樣的高級題目。
讀者應(yīng)具備的背景知識
本書的重點(diǎn)是執(zhí)行x86-64機(jī)器代碼的系統(tǒng)。對英特爾及其競爭對手而言,x86-64是他們自1978年起,以8086微處理器為代表,不斷進(jìn)化的最新成果。按照英特爾微處理器產(chǎn)品線的命名規(guī)則,這類微處理器俗稱為“x86”。隨著半導(dǎo)體技術(shù)的演進(jìn),單芯片上集成了更多的晶體管,這些處理器的計(jì)算能力和內(nèi)存容量有了很大的增長。在這個(gè)過程中,它們從處理16位字,發(fā)展到引入IA32處理器處理32位字,再到最近的x86-64處理64位字。
我們考慮的是這些機(jī)器如何在Linux操作系統(tǒng)上運(yùn)行C語言程序。Linux是眾多繼承自最初由貝爾實(shí)驗(yàn)室開發(fā)的Unix的操作系統(tǒng)中的一種。這類操作系統(tǒng)的其他成員包括Solaris、FreeBSD和MacOS X。近年來,由于Posix和標(biāo)準(zhǔn)Unix規(guī)范的標(biāo)準(zhǔn)化努力,這些操作系統(tǒng)保持了高度兼容性。因此,本書內(nèi)容幾乎直接適用于這些“類Unix”操作系統(tǒng)。
文中包含大量已在Linux系統(tǒng)上編譯和運(yùn)行過的程序示例。我們假設(shè)你能訪問一臺這樣的機(jī)器,并且能夠登錄,做一些諸如切換目錄之類的簡單操作。如果你的計(jì)算機(jī)運(yùn)行的是Microsoft Windows系統(tǒng),我們建議你選擇安裝一個(gè)虛擬機(jī)環(huán)境(例如VirtualBox或者VMWare),以便為一種操作系統(tǒng)(客戶OS)編寫的程序能在另一種系統(tǒng)(宿主OS)上運(yùn)行。
我們還假設(shè)你對C和C++有一定的了解。如果你以前只有Java經(jīng)驗(yàn),那么你需要付出更多的努力來完成這種轉(zhuǎn)換,不過我們也會幫助你。Java和C有相似的語法和控制語句。不過,有一些C語言的特性(特別是指針、顯式的動態(tài)內(nèi)存分配和格式化I/O)在Java中都是沒有的。所幸的是,C是一個(gè)較小的語言,在Brian Kernighan和Dennis Ritchie經(jīng)典的“K&R”文獻(xiàn)中得到了清晰優(yōu)美的描述[61]。無論你的編程背景如何,都應(yīng)該考慮將K&R作為個(gè)人系統(tǒng)藏書的一部分。如果你只有使用解釋性語言的經(jīng)驗(yàn),如Python、Ruby或Perl,那么在使用本書之前,需要花費(fèi)一些時(shí)間來學(xué)習(xí)C。
本書的前幾章揭示了C語言程序和它們相對應(yīng)的機(jī)器語言程序之間的交互作用。機(jī)器語言示例都是用運(yùn)行在x86-64處理器上的GNU GCC編譯器生成的。我們不需要你以前有任何硬件、機(jī)器語言或是匯編語言編程的經(jīng)驗(yàn)。
給C語言初學(xué)者 關(guān)于C編程語言的建議
為了幫助C語言編程背景薄弱(或全無背景)的讀者,我們在書中加入了這樣一些專門的注釋來突出C中一些特別重要的特性。我們假設(shè)你熟悉C++或Java。
如何閱讀此書
從程序員的角度學(xué)習(xí)計(jì)算機(jī)系統(tǒng)是如何工作的會非常有趣,主要是因?yàn)槟憧梢灾鲃拥刈鲞@件事情。無論何時(shí)你學(xué)到一些新的東西,都可以馬上試驗(yàn)并且直接看到運(yùn)行結(jié)果。事實(shí)上,我們相信學(xué)習(xí)系統(tǒng)的唯一方法就是做(do)系統(tǒng),即在真正的系統(tǒng)上解決具體的問題,或是編寫和運(yùn)行程序。
這個(gè)主題觀念貫穿全書。當(dāng)引入一個(gè)新概念時(shí),將會有一個(gè)或多個(gè)練習(xí)題緊隨其后,你應(yīng)該馬上做一做來檢驗(yàn)?zāi)愕睦斫。這些練習(xí)題的解答在每章的末尾。當(dāng)你閱讀時(shí),嘗試自己來解答每個(gè)問題,然后再查閱答案,看自己的答案是否正確。除第1章外,每章后面都有難度不同的家庭作業(yè)。對每個(gè)家庭作業(yè)題,我們標(biāo)注了難度級別:
*只需要幾分鐘。幾乎或完全不需要編程。
**可能需要將近20分鐘。通常包括編寫和測試一些代碼。(許多都源自我們在考試中出的題目。)
需要很大的努力,也許是1~2個(gè)小時(shí)。一般包括編寫和測試大量的代碼。
一個(gè)實(shí)驗(yàn)作業(yè),需要將近10個(gè)小時(shí)。
文中每段代碼示例都是由經(jīng)過GCC編譯的C程序直接生成并在Linux系統(tǒng)上進(jìn)行了測試,沒有任何人為的改動。當(dāng)然,你的系統(tǒng)上GCC的版本可能不同,或者根本就是另外一種編譯器,那么可能生成不一樣的機(jī)器代碼,但是整體行為表現(xiàn)應(yīng)該是一樣的。所有的源程序代碼都可以從csapp.cs.cmu.edu上的CS:APP主頁上獲取。在本書中,源程序的文件名列在兩條水平線的右邊,水平線之間是格式化的代碼。比如,圖1中的程序能在code/intro/目錄下的hello.c文件中找到。當(dāng)遇到這些示例程序時(shí),我們鼓勵(lì)你在自己的系統(tǒng)上試著運(yùn)行它們。
圖1 一個(gè)典型的代碼示例
為了避免本書體積過大、內(nèi)容過多,我們添加了許多網(wǎng)絡(luò)旁注(Web aside),包括一些對本書主要內(nèi)容的補(bǔ)充資料。本書中用CHAP:TOP這樣的標(biāo)記形式來引用這些旁注,這里CHAP是該章主題的縮寫編碼,而TOP是涉及的話題的縮寫編碼。例如,網(wǎng)絡(luò)旁注DATA:BOOL包含對第2章中數(shù)據(jù)表示里面有關(guān)布爾代數(shù)內(nèi)容的補(bǔ)充資料;而網(wǎng)絡(luò)旁注ARCH:VLOG包含的是用Verilog硬件描述語言進(jìn)行處理器設(shè)計(jì)的資料,是對第4章中處理器設(shè)計(jì)部分的補(bǔ)充。所有的網(wǎng)絡(luò)旁注都可以從CS:APP的主頁上獲取。
旁注 什么是旁注
在整本書中,你將會遇到很多以這種形式出現(xiàn)的旁注。旁注是附加說明,能使你對當(dāng)前討論的主題多一些了解。旁注可以有很多用處。一些是小的歷史故事。例如,C語言、Linux和Internet是從何而來的?有些旁注則是用來澄清學(xué)生們經(jīng)常感到疑惑的問題。例如,高速緩存的行、組和塊有什么區(qū)別?還有些旁注給出了一些現(xiàn)實(shí)世界的例子。例如,一個(gè)浮點(diǎn)錯(cuò)誤怎么毀掉了法國的一枚火箭,或是給出市面上出售的一個(gè)磁盤驅(qū)動器的幾何和運(yùn)行參數(shù)。最后,還有一些旁注僅僅就是一些有趣的內(nèi)容,例如,什么是“hoinky”?
本書概述
本書由12章組成,旨在闡述計(jì)算機(jī)系統(tǒng)的核心概念。內(nèi)容概述如下:
第1章:計(jì)算機(jī)系統(tǒng)漫游。這一章通過研究“hello,world”這個(gè)簡單程序的生命周期,介紹計(jì)算機(jī)系統(tǒng)的主要概念和主題。
第2章:信息的表示和處理。我們講述了計(jì)算機(jī)的算術(shù)運(yùn)算,重點(diǎn)描述了會對程序員有影響的無符號數(shù)和數(shù)的補(bǔ)碼表示的特性。我們考慮數(shù)字是如何表示的,以及由此確定對于一個(gè)給定的字長,其可能編碼值的范圍。我們探討有符號和無符號數(shù)字之間類型轉(zhuǎn)換的效果,還闡述算術(shù)運(yùn)算的數(shù)學(xué)特性。菜鳥級程序員經(jīng)常很驚奇地了解到(用補(bǔ)碼表示的)兩個(gè)正數(shù)的和或者積可能為負(fù)。另一方面,補(bǔ)碼的算術(shù)運(yùn)算滿足很多整數(shù)運(yùn)算的代數(shù)特性,因此,編譯器可以很安全地把一個(gè)常量乘法轉(zhuǎn)化為一系列的移位和加法。我們用C語言的位級操作來說明布爾代數(shù)的原理和應(yīng)用。我們從兩個(gè)方面講述了IEEE標(biāo)準(zhǔn)的浮點(diǎn)格式:一是如何用它來表示數(shù)值,一是浮點(diǎn)運(yùn)算的數(shù)學(xué)屬性。
對計(jì)算機(jī)的算術(shù)運(yùn)算有深刻的理解是寫出可靠程序的關(guān)鍵。比如,程序員和編譯器不能用表達(dá)式(x-y<0)來替代(x 第3章:程序的機(jī)器級表示。我們教讀者如何閱讀由C編譯器生成的x86-64機(jī)器代碼。我們說明為不同控制結(jié)構(gòu)(比如條件、循環(huán)和開關(guān)語句)生成的基本指令模式。我們還講述過程的實(shí)現(xiàn),包括棧分配、寄存器使用慣例和參數(shù)傳遞。我們討論不同數(shù)據(jù)結(jié)構(gòu)(如結(jié)構(gòu)、聯(lián)合和數(shù)組)的分配和訪問方式。我們還說明實(shí)現(xiàn)整數(shù)和浮點(diǎn)數(shù)算術(shù)運(yùn)算的指令。我們還以分析程序在機(jī)器級的樣子作為途徑,來理解常見的代碼安全漏洞(例如緩沖區(qū)溢出),以及理解程序員、編譯器和操作系統(tǒng)可以采取的減輕這些威脅的措施。學(xué)習(xí)本章的概念能夠幫助讀者成為更好的程序員,因?yàn)槟銈兌贸绦蛟跈C(jī)器上是如何表示的。另外一個(gè)好處就在于讀者會對指針有非常全面而具體的理解。
第4章:處理器體系結(jié)構(gòu)。這一章講述基本的組合和時(shí)序邏輯元素,并展示這些元素如何在數(shù)據(jù)通路中組合到一起,來執(zhí)行x86-64指令集的一個(gè)稱為“Y86-64”的簡化子集。我們從設(shè)計(jì)單時(shí)鐘周期數(shù)據(jù)通路開始。這個(gè)設(shè)計(jì)概念上非常簡單,但是運(yùn)行速度不會太快。然后我們引入流水線的思想,將處理一條指令所需要的不同步驟實(shí)現(xiàn)為獨(dú)立的階段。這個(gè)設(shè)計(jì)中,在任何時(shí)刻,每個(gè)階段都可以處理不同的指令。我們的五階段處理器流水線更加實(shí)用。本章中處理器設(shè)計(jì)的控制邏輯是用一種稱為HCL的簡單硬件描述語言來描述的。用HCL寫的硬件設(shè)計(jì)能夠編譯和鏈接到本書提供的模擬器中,還可以根據(jù)這些設(shè)計(jì)生成Verilog描述,它適合合成到實(shí)際可以運(yùn)行的硬件上去。
第5章:優(yōu)化程序性能。在這一章里,我們介紹了許多提高代碼性能的技術(shù),主要思想就是讓程序員通過使編譯器能夠生成更有效的機(jī)器代碼來學(xué)習(xí)編寫C代碼。我們一開始介紹的是減少程序需要做的工作的變換,這些是在任何機(jī)器上寫任何程序時(shí)都應(yīng)該遵循的。然后講的是增加生成的機(jī)器代碼中指令級并行度的變換,因而提高了程序在現(xiàn)代“超標(biāo)量”處理器上的性能。為了解釋這些變換行之有效的原理,我們介紹了一個(gè)簡單的操作模型,它描述了現(xiàn)代亂序處理器是如何工作的,然后給出了如何根據(jù)一個(gè)程序的圖形化表示中的關(guān)鍵路徑來測量一個(gè)程序可能的性能。你會驚訝于對C代碼做一些簡單的變換能給程序帶來多大的速度提升。
第6章:存儲器層次結(jié)構(gòu)。對應(yīng)用程序員來說,存儲器系統(tǒng)是計(jì)算機(jī)系統(tǒng)中最直接可見的部分之一。到目前為止,讀者一直認(rèn)同這樣一個(gè)存儲器系統(tǒng)概念模型,認(rèn)為它是一個(gè)有一致訪問時(shí)間的線性數(shù)組。實(shí)際上,存儲器系統(tǒng)是一個(gè)由不同容量、造價(jià)和訪問時(shí)間的存儲設(shè)備組成的層次結(jié)構(gòu)。我們講述不同類型的隨機(jī)存取存儲器(RAM)和只讀存儲器(ROM),以及磁盤和固態(tài)硬盤的幾何形狀和組織構(gòu)造。我們描述這些存儲設(shè)備是如何放置在層次結(jié)構(gòu)中的,講述訪問局部性是如何使這種層次結(jié)構(gòu)成為可能的。我們通過一個(gè)獨(dú)特的觀點(diǎn)使這些理論具體化,那就是將存儲器系統(tǒng)視為一個(gè)“存儲器山”,山脊是時(shí)間局部性,而斜坡是空間局部性。最后,我們向讀者闡述如何通過改善程序的時(shí)間局部性和空間局部性來提高應(yīng)用程序的性能。
第7章:鏈接。本章講述靜態(tài)和動態(tài)鏈接,包括的概念有可重定位的和可執(zhí)行的目標(biāo)文件、符號解析、重定位、靜態(tài)庫、共享目標(biāo)庫、位置無關(guān)代碼,以及庫打樁。大多數(shù)講述系統(tǒng)的書中都不講鏈接,我們要講述它是出于以下原因。第一,程序員遇到的最令人迷惑的問題中,有一些和鏈接時(shí)的小故障有關(guān),尤其是對那些大型軟件包來說。第二,鏈接器生成的目標(biāo)文件是與一些像加載、虛擬內(nèi)存和內(nèi)存映射這樣的概念相關(guān)的。
第8章:異常控制流。在本書的這個(gè)部分,我們通過介紹異?刂屏鳎闯7种Ш瓦^程調(diào)用以外的控制流的變化)的一般概念,打破單一程序的模型。我們給出存在于系統(tǒng)所有層次的異?刂屏鞯睦,從底層的硬件異常和中斷,到并發(fā)進(jìn)程的上下文切換,到由于接收Linux信號引起的控制流突變,到C語言中破壞棧原則的非本地跳轉(zhuǎn)。
在這一章,我們介紹進(jìn)程的基本概念,進(jìn)程是對一個(gè)正在執(zhí)行的程序的一種抽象。讀者會學(xué)習(xí)進(jìn)程是如何工作的,以及如何在應(yīng)用程序中創(chuàng)建和操縱進(jìn)程。我們會展示應(yīng)用程序員如何通過Linux系統(tǒng)調(diào)用來使用多個(gè)進(jìn)程。學(xué)完本章之后,讀者就能夠編寫帶作業(yè)控制的Linux shell了。同時(shí),這里也會向讀者初步展示程序的并發(fā)執(zhí)行會引起不確定的行為。
第9章:虛擬內(nèi)存。我們講述虛擬內(nèi)存系統(tǒng)是希望讀者對它是如何工作的以及它的特性有所了解。我們想讓讀者了解為什么不同的并發(fā)進(jìn)程各自都有一個(gè)完全相同的地址范圍,能共享某些頁,而又獨(dú)占另外一些頁。我們還講了一些管理和操縱虛擬內(nèi)存的問題。特別地,我們討論了存儲分配操作,就像標(biāo)準(zhǔn)庫的malloc和free操作。闡述這些內(nèi)容是出于下面幾個(gè)目的。它加強(qiáng)了這樣一個(gè)概念,那就是虛擬內(nèi)存空間只是一個(gè)字節(jié)數(shù)組,程序可以把它劃分成不同的存儲單元。它可以幫助讀者理解當(dāng)程序包含存儲泄漏和非法指針引用等內(nèi)存引用錯(cuò)誤時(shí)的后果。最后,許多應(yīng)用程序員編寫自己的優(yōu)化了的存儲分配操作來滿足應(yīng)用程序的需要和特性。這一章比其他任何一章都更能展現(xiàn)將計(jì)算機(jī)系統(tǒng)中的硬件和軟件結(jié)合起來闡述的優(yōu)點(diǎn)。而傳統(tǒng)的計(jì)算機(jī)體系結(jié)構(gòu)和操作系統(tǒng)書籍都只講述虛擬內(nèi)存的某一方面。
第10章:系統(tǒng)級I/O。我們講述Unix I/O的基本概念,例如文件和描述符。我們描述如何共享文件,I/O重定向是如何工作的,還有如何訪問文件的元數(shù)據(jù)。我們還開發(fā)了一個(gè)健壯的帶緩沖區(qū)的I/O包,可以正確處理一種稱為short counts的奇特行為,也就是庫函數(shù)只讀取一部分的輸入數(shù)據(jù)。我們闡述C的標(biāo)準(zhǔn)I/O庫,以及它與Linux I/O的關(guān)系,重點(diǎn)談到標(biāo)準(zhǔn)I/O的局限性,這些局限性使之不適合網(wǎng)絡(luò)編程。總的來說,本章的主題是后面兩章—網(wǎng)絡(luò)和并發(fā)編程的基礎(chǔ)。
第11章:網(wǎng)絡(luò)編程。對編程而言,網(wǎng)絡(luò)是非常有趣的I/O設(shè)備,它將許多我們前面文中學(xué)習(xí)的概念(比如進(jìn)程、信號、字節(jié)順序、內(nèi)存映射和動態(tài)內(nèi)存分配)聯(lián)系在一起。網(wǎng)絡(luò)程序還為下一章的主題—并發(fā),提供了一個(gè)很令人信服的上下文。本章只是網(wǎng)絡(luò)編程的一個(gè)很小的部分,使讀者能夠編寫一個(gè)簡單的Web服務(wù)器。我們還講述位于所有網(wǎng)絡(luò)程序底層的客戶端服務(wù)器模型。我們展現(xiàn)了一個(gè)程序員對Internet的觀點(diǎn),并且教讀者如何用套接字接口來編寫Internet客戶端和服務(wù)器。最后,我們介紹超文本傳輸協(xié)議(HTTP),并開發(fā)了一個(gè)簡單的迭代式Web服務(wù)器。
第12章:并發(fā)編程。這一章以Internet服務(wù)器設(shè)計(jì)為例介紹了并發(fā)編程。我們比較對照了三種編寫并發(fā)程序的基本機(jī)制(進(jìn)程、I/O多路復(fù)用和線程),并且展示如何用它們來建造并發(fā)Internet服務(wù)器。我們探討了用P、V信號量操作來實(shí)現(xiàn)同步、線程安全和可重入、競爭條件以及死鎖等的基本原則。對大多數(shù)服務(wù)器應(yīng)用來說,寫并發(fā)代碼都是很關(guān)鍵的。我們還講述了線程級編程的使用方法,用這種方法來表達(dá)應(yīng)用程序中的并行性,使得程序在多核處理器上能執(zhí)行得更快。使用所有的核解決同一個(gè)計(jì)算問題需要很小心謹(jǐn)慎地協(xié)調(diào)并發(fā)線程,既要保證正確性,又要爭取獲得高性能。
本版新增內(nèi)容
本書的第1版于2003年出版,第2版在2011年出版?紤]到計(jì)算機(jī)技術(shù)發(fā)展如此迅速,這本書的內(nèi)容還算是保持得很好。事實(shí)證明Intel x86的機(jī)器上運(yùn)行Linux(以及相關(guān)操作系統(tǒng)),加上采用C語言編程,是一種能夠涵蓋當(dāng)今許多系統(tǒng)的組合。然而,硬件技術(shù)、編譯器和程序庫接口的變化,以及很多教師教授這些內(nèi)容的經(jīng)驗(yàn),都促使我們做了大量的修改。
第2版以來的最大整體變化是,我們的介紹從以IA32和x86-64為基礎(chǔ),轉(zhuǎn)變?yōu)橥耆詘86-64為基礎(chǔ)。這種重心的轉(zhuǎn)移影響了很多章節(jié)的內(nèi)容。下面列出一些明顯的變化:
第1章。我們將第5章對Amdahl定理的討論移到了本章。
第2章。讀者和評論家的反饋是一致的,本章的一些內(nèi)容有點(diǎn)令人不知所措。因此,我們澄清了一些知識點(diǎn),用更加數(shù)學(xué)的方式來描述,使得這些內(nèi)容更容易理解。這使得讀者能先略過數(shù)學(xué)細(xì)節(jié),獲得高層次的總體概念,然后回過頭來進(jìn)行更細(xì)致深入的閱讀。
第3章。我們將之前基于IA32和x86-64的表現(xiàn)形式轉(zhuǎn)換為完全基于x86-64,還更新了近期版本GCC產(chǎn)生的代碼。其結(jié)果是大量的重寫工作,包括修改了一些概念提出的順序。同時(shí),我們還首次介紹了對處理浮點(diǎn)數(shù)據(jù)的程序的機(jī)器級支持。由于歷史原因,我們給出了一個(gè)網(wǎng)絡(luò)旁注描述IA32機(jī)器碼。
第4章。我們將之前基于32位架構(gòu)的處理器設(shè)計(jì)修改為支持64位字和操作的設(shè)計(jì)。
第5章。我們更新了內(nèi)容以反映最近幾代x86-64處理器的性能。通過引入更多的功能單元和更復(fù)雜的控制邏輯,我們開發(fā)的基于程序數(shù)據(jù)流表示的程序性能模型,其性能預(yù)測變得比之前更加可靠。
第6章。我們對內(nèi)容進(jìn)行了更新,以反映更多的近期技術(shù)。
第7章。針對x86-64,我們重寫了本章,擴(kuò)充了關(guān)于用GOT和PLT創(chuàng)建位置無關(guān)代碼的討論,新增了一節(jié)描述更加強(qiáng)大的鏈接技術(shù),比如庫打樁。
第8章。我們增加了對信號處理程序更細(xì)致的描述,包括異步信號安全的函數(shù),編寫信號處理程序的具體指導(dǎo)原則,以及用sigsuspend等待處理程序。
第9章。本章變化不大。
第10章。我們新增了一節(jié)說明文件和文件的層次結(jié)構(gòu),除此之外,本章的變化不大。
第11章。我們介紹了采用最新getaddrinfo和getnameinfo函數(shù)的、與協(xié)議無關(guān)和線程安全的網(wǎng)絡(luò)編程,取代過時(shí)的、不可重入的gethostbyname和gethostbyaddr函數(shù)。
第12章。我們擴(kuò)充了利用線程級并行性使得程序在多核機(jī)器上更快運(yùn)行的內(nèi)容。
此外,我們還增加和修改了很多練習(xí)題和家庭作業(yè)。
本書的起源
本書起源于1998年秋季,我們在卡內(nèi)基–梅。–MU)大學(xué)開設(shè)的一門編號為15-213的介紹性課程:計(jì)算機(jī)系統(tǒng)導(dǎo)論(Introduction to Computer System,ICS)[14]。從那以后,每學(xué)期都開設(shè)了ICS這門課程,每學(xué)期有超過400名學(xué)生上課,這些學(xué)生從本科二年級到碩士研究生都有,所學(xué)專業(yè)也很廣泛。這門課程是卡內(nèi)基–梅隆大學(xué)計(jì)算機(jī)科學(xué)系(CS)以及電子和計(jì)算機(jī)工程系(ECE)所有本科生的必修課,也是CS和ECE大多數(shù)高級系統(tǒng)課程的先行必修課。
ICS這門課程的宗旨是用一種不同的方式向?qū)W生介紹計(jì)算機(jī)。因?yàn),我們的學(xué)生中幾乎沒有人有機(jī)會親自去構(gòu)造一個(gè)計(jì)算機(jī)系統(tǒng)。另一方面,大多數(shù)學(xué)生,甚至包括所有的計(jì)算機(jī)科學(xué)家和計(jì)算機(jī)工程師,也需要日常使用計(jì)算機(jī)和編寫計(jì)算機(jī)程序。所以我們決定從程序員的角度來講解系統(tǒng),并采用這樣的原則過濾要講述的內(nèi)容:我們只討論那些影響用戶級C語言程序的性能、正確性或?qū)嵱眯缘闹黝}。
比如,我們排除了諸如硬件加法器和總線設(shè)計(jì)這樣的主題。雖然我們談及了機(jī)器語言,但是重點(diǎn)并不在于如何手工編寫匯編語言,而是關(guān)注C語言編譯器是如何將C語言的結(jié)構(gòu)翻譯成機(jī)器代碼的,包括編譯器是如何翻譯指針、循環(huán)、過程調(diào)用以及開關(guān)(switch)語句的。更進(jìn)一步地,我們將更廣泛和全盤地看待系統(tǒng),包括硬件和系統(tǒng)軟件,涵蓋了包括鏈接、加載、進(jìn)程、信號、性能優(yōu)化、虛擬內(nèi)存、I/O以及網(wǎng)絡(luò)與并發(fā)編程等在內(nèi)的主題。
這種做法使得我們講授ICS課程的方式對學(xué)生來講既實(shí)用、具體,還能動手操作,同時(shí)也非常能調(diào)動學(xué)生的積極性。很快地,我們收到來自學(xué)生和教職工非常熱烈而積極的反響,我們意識到卡內(nèi)基梅隆大學(xué)以外的其他人也可以從我們的方法中獲益。因此,這本書從ICS課程的筆記中應(yīng)運(yùn)而生了,而現(xiàn)在我們對它做了修改,使之能夠反映科學(xué)技術(shù)以及計(jì)算機(jī)系統(tǒng)實(shí)現(xiàn)中的變化和進(jìn)步。
通過本書的多個(gè)版本和多種語言譯本,ICS和許多相似課程已經(jīng)成為世界范圍內(nèi)數(shù)百所高校的計(jì)算機(jī)科學(xué)和計(jì)算機(jī)工程課程的一部分。
寫給指導(dǎo)教師們:可以基于本書的課程
指導(dǎo)教師可以使用本書來講授五種不同類型的系統(tǒng)課程(見圖2)。具體每門課程則有賴于課程大綱的要求、個(gè)人喜好、學(xué)生的背景和能力。圖中的課程從左往右越來越強(qiáng)調(diào)以程序員的角度來看待系統(tǒng)。以下是簡單的描述。
ORG:一門以非傳統(tǒng)風(fēng)格講述傳統(tǒng)主題的計(jì)算機(jī)組成原理課程。傳統(tǒng)的主題包括邏輯設(shè)計(jì)、處理器體系結(jié)構(gòu)、匯編語言和存儲器系統(tǒng),然而這里更多地強(qiáng)調(diào)了對程序員的影響。例如,要反過來考慮數(shù)據(jù)表示對C語言程序的數(shù)據(jù)類型和操作的影響。又例如,對匯編代碼的講解是基于C語言編譯器產(chǎn)生的機(jī)器代碼,而不是手工編寫的匯編代碼。
ORG+:一門特別強(qiáng)調(diào)硬件對應(yīng)用程序性能影響的ORG課程。和ORG課程相比,學(xué)生要更多地學(xué)習(xí)代碼優(yōu)化和改進(jìn)C語言程序的內(nèi)存性能。
ICS:基本的ICS課程,旨在培養(yǎng)一類程序員,他們能夠理解硬件、操作系統(tǒng)和編譯系統(tǒng)對應(yīng)用程序的性能和正確性的影響。和ORG+課程的一個(gè)顯著不同是,本課程不涉及低層次的處理器體系結(jié)構(gòu)。相反,程序員只同現(xiàn)代亂序處理器的高級模型打交道。ICS課程非常適合安排到一個(gè)10周的小學(xué)期,如果期望步調(diào)更從容一些,也可以延長到一個(gè)15周的學(xué)期。
ICS+:在基本的ICS課程基礎(chǔ)上,額外論述一些系統(tǒng)編程的問題,比如系統(tǒng)級I/O、網(wǎng)絡(luò)編程和并發(fā)編程。這是卡內(nèi)基–梅隆大學(xué)的一門一學(xué)期時(shí)長的課程,會講述本書中除了低級處理器體系結(jié)構(gòu)以外的所有章。
SP:一門系統(tǒng)編程課程。和ICS+課程相似,但是剔除了浮點(diǎn)和性能優(yōu)化的內(nèi)容,更加強(qiáng)調(diào)系統(tǒng)編程,包括進(jìn)程控制、動態(tài)鏈接、系統(tǒng)級I/O、網(wǎng)絡(luò)編程和并發(fā)編程。指導(dǎo)教師可能會想從其他渠道對某些高級主題做些補(bǔ)充,比如守護(hù)進(jìn)程(daemon)、終端控制和Unix IPC(進(jìn)程間通信)。
……
Randal E.Bryant
David R.O扝allaron
于匹茲堡,賓夕法尼亞州
Randal E.Bryant,1981年于麻省理工學(xué)院獲得計(jì)算機(jī)博士學(xué)位,1984年至今任教于卡內(nèi)基-梅隆大學(xué),F(xiàn)任卡內(nèi)基-梅隆大學(xué)計(jì)算機(jī)科學(xué)學(xué)院院長、教授,同時(shí)還受邀任教于電子和計(jì)算機(jī)工程系。他從事本科生和研究生計(jì)算機(jī)系統(tǒng)方面課程的教學(xué)近40年,和O’Hallaron教授一起在卡內(nèi)基-梅隆大學(xué)開設(shè)了15-213課程“計(jì)算機(jī)系統(tǒng)導(dǎo)論”,那便是本書的基礎(chǔ)。他還是ACM院士、IEEE院士、美國國家工程院院士和美國人文與科學(xué)研究院院士。其研究成果被Intel、IBM、Fujitsu和Microsoft等主要計(jì)算機(jī)制造商使用,他還因研究獲得過Semiconductor Research Corporation、ACM、IEEE頒發(fā)的多項(xiàng)大獎。
David R.O’Hallaron,卡內(nèi)基-梅隆大學(xué)電子和計(jì)算機(jī)工程系教授。在弗吉尼亞大學(xué)獲得計(jì)算機(jī)科學(xué)的博士學(xué)位,2007年-2010年為Intel匹茲堡實(shí)驗(yàn)室主任。他教授本科生和研究生的計(jì)算機(jī)系統(tǒng)方面的課程已有20余年,并和Bryant教授一起教授“計(jì)算機(jī)系統(tǒng)導(dǎo)論”課程。曾獲得卡內(nèi)基-梅隆大學(xué)計(jì)算機(jī)學(xué)院頒發(fā)的Herbert Simon杰出教學(xué)獎。他主要從事計(jì)算機(jī)系統(tǒng)領(lǐng)域的研究,與Quake項(xiàng)目成員一起獲得過高性能計(jì)算領(lǐng)域中的*高國際獎項(xiàng)——Gordon Bell獎。他目前的工作重點(diǎn)是研究自動分級(autograding)概念,即評價(jià)其他程序質(zhì)量的程序。
Preface xix About the Authors xxxv
1 A Tour of Computer Systems 1
1.1 Information Is Bits + Context 3
1.2 Programs Are Translated by Other Programs into Different Forms 4
1.3 It Pays to Understand How Compilation Systems Work 6
1.4 Processors Read and Interpret Instructions Stored in Memory 7
1.5 Caches Matter 11
1.6 Storage Devices Form a Hierarchy 14
1.7 The Operating System Manages the Hardware 14
1.8 Systems Communicate with Other Systems Using Networks 19
1.9 Important Themes 22
1.10 Summary 27 Bibliographic Notes 28 Solutions to Practice Problems 28
Part I Program Structure and Execution
2 Representing and Manipulating Information 31
2.1 Information Storage 34
2.2 Integer Representations 59
2.3 Integer Arithmetic 84
2.4 Floating Point 108
2.5 Summary 126
Bibliographic Notes 127
Homework Problems 128
Solutions to Practice Problems 143
3 Machine-Level Representation of Programs 163
3.1 A Historical Perspective 166
3.2 Program Encodings 169
3.3 Data Formats 177
3.4 Accessing Information 179
3.5 Arithmetic and Logical Operations 191
3.6 Control 200
3.7 Procedures 238
3.8 Array Allocation and Access 255
3.9 Heterogeneous Data Structures 265
3.10 Combining Control and Data in Machine-Level Programs 276
3.11 Floating-Point Code 293
3.12 Summary 309
Bibliographic Notes 310
Homework Problems 311
Solutions to Practice Problems 325
4 Processor Architecture 351
4.1 The Y86-64 Instruction Set Architecture 355
4.2 Logic Design and the Hardware Control Language HCL 372
4.3 Sequential Y86-64 Implementations 384
4.4 General Principles of Pipelining 412
4.5 Pipelined Y86-64 Implementations 421
4.6 Summary 470
4.6.1 Y86-64 Simulators 472
Bibliographic Notes 473
Homework Problems 473
Solutions to Practice Problems 480
5 Optimizing Program Performance 495
5.1 Capabilities and Limitations of Optimizing Compilers 498
5.2 Expressing Program Performance 502
5.3 Program Example 504
5.4 Eliminating Loop Inef.ciencies 508
5.5 Reducing Procedure Calls 512
5.6 Eliminating Unneeded Memory References 514
5.7 Understanding Modern Processors 517
5.8 Loop Unrolling 531
5.9 Enhancing Parallelism 536
5.10 Summary of Results for Optimizing Combining Code 547
5.11 Some Limiting Factors 548
5.12 Understanding Memory Performance 553
5.13 Life in the Real World: Performance Improvement Techniques 561
5.14 Identifying and Eliminating Performance Bottlenecks 562
5.15 Summary 568
Bibliographic Notes 569
Homework Problems 570
Solutions to Practice Problems 573
6 The Memory Hierarchy 579
6.1 Storage Technologies 581
6.2 Locality 604
6.3 The Memory Hierarchy 609
6.4 Cache Memories 614
6.5 Writing Cache-Friendly Code 633
6.6 Putting It Together: The Impact of Caches on Program Performance 639
6.7 Summary 648
Bibliographic Notes 648
Homework Problems 649
Solutions to Practice Problems 660
Part II Running Programs on a System
7 Linking 669
7.1 Compiler Drivers 671
7.2 Static Linking 672
7.3 Object Files 673
7.4 Relocatable Object Files 674
7.5 Symbols and Symbol Tables 675
7.6 Symbol Resolution 679
7.7 Relocation 689
7.8 Executable Object Files 695
7.9 Loading Executable Object Files 697
7.10 Dynamic Linking with Shared Libraries 698
7.11 Loading and Linking Shared Libraries from Applications 701
7.12 Position-Independent Code (PIC) 704
7.13 Library Interpositioning 707
7.14 Tools for Manipulating Object Files 713
7.15 Summary 713
Bibliographic Notes 714
Homework Problems 714
Solutions to Practice Problems 717
8 Exceptional Control Flow 721
8.1 Exceptions 723
8.2 Processes 732
8.3 System Call Error Handling 737
8.4 Process Control 738
8.5 Signals 756
8.6 Nonlocal Jumps 781
8.7 Tools for Manipulating Processes 786
8.8 Summary 787
Bibliographic Notes 787
Homework Problems 788
Solutions to Practice Problems 795
9 Virtual Memory 801
9.1 Physical and Virtual Addressing 803
9.2 Address Spaces 804
9.3 VM as a Tool for Caching 805
9.4 VM as a Tool for Memory Management 811
9.5 VM as a Tool for Memory Protection 812
9.6 Address Translation 813
9.7 Case Study: The Intel Core i7/Linux Memory System 825
9.8 Memory Mapping 833
9.9 Dynamic Memory Allocation 839
9.10 Garbage Collection 865
9.11 Common Memory-Related Bugs in C Programs 870
9.12 Summary 875
Bibliographic Notes 876
Homework Problems 876
Solutions to Practice Problems 880
Part III Interaction and Communication between Programs
10 System-Level I/O 889
11 Network Programming 917
12 Concurrent Programming 971
12.1 Concurrent Programming with Processes 973
12.2 Concurrent Programming with I/O Multiplexing 977
12.3 Concurrent Programming with Threads 985
12.4 Shared Variables in Threaded Programs 992
12.5 Synchronizing Threads with Semaphores 995
12.6 Using Threads for Parallelism 1013
12.7 Other Concurrency Issues 1020
12.8 Summary 1030
你還可能感興趣
我要評論
|