本書是將計算機(jī)軟件和硬件理論結(jié)合講述的經(jīng)典教程,內(nèi)容覆蓋計算機(jī)導(dǎo)論、體系結(jié)構(gòu)和處理器設(shè)計等多門課程。本書的大優(yōu)點(diǎn)是為程序員描述計算機(jī)系統(tǒng)的實現(xiàn)細(xì)節(jié),通過描述程序是如何映射到系統(tǒng)上,以及程序是如何執(zhí)行的,使讀者更好地理解程序的行為為什么是這樣的,以及造成效率低下的原因。
第二版銷售突破100000冊,第三版重磅上市!
理解計算機(jī)系統(tǒng)首*書目, 10余萬程序員的共同選擇
卡內(nèi)基-梅隆、北京大學(xué)、清華大學(xué)、上海交通大學(xué)等國內(nèi)外眾多知名高校選用指定教材
從程序員視角全面剖析的實現(xiàn)細(xì)節(jié),使讀者深刻理解程序的行為,將所有計算機(jī)系統(tǒng)的相關(guān)知識融會貫通。
新版本全面基于X86-64位處理器
全新的閱讀和學(xué)習(xí)體驗:由國內(nèi)名師錄制章前導(dǎo)讀,使讀者可以了解各章的重點(diǎn)內(nèi)容和知識關(guān)聯(lián),形成關(guān)于計算機(jī)系統(tǒng)的知識架構(gòu)。并開設(shè)了本書的網(wǎng)絡(luò)社區(qū),讀者可加入社區(qū),獲得本書相關(guān)學(xué)習(xí)資源,了解活動信息。
前言
本書(簡稱CS:APP)的主要讀者是計算機(jī)科學(xué)家、計算機(jī)工程師,以及那些想通過學(xué)習(xí)計算機(jī)系統(tǒng)的內(nèi)在運(yùn)作而能夠?qū)懗龈贸绦虻娜恕?
我們的目的是解釋所有計算機(jī)系統(tǒng)的本質(zhì)概念,并向你展示這些概念是如何實實在在地影響應(yīng)用程序的正確性、性能和實用性的。其他的系統(tǒng)類書籍都是從構(gòu)建者的角度來寫的,講述如何實現(xiàn)硬件或系統(tǒng)軟件,包括操作系統(tǒng)、編譯器和網(wǎng)絡(luò)接口。而本書是從程序員的角度來寫的,講述應(yīng)用程序員如何能夠利用系統(tǒng)知識來編寫出更好的程序。當(dāng)然,學(xué)習(xí)一個計算機(jī)系統(tǒng)應(yīng)該做些什么,是學(xué)習(xí)如何構(gòu)建一個計算機(jī)系統(tǒng)的很好的出發(fā)點(diǎn),所以,對于希望繼續(xù)學(xué)習(xí)系統(tǒng)軟硬件實現(xiàn)的人來說,本書也是一本很有價值的介紹性讀物。大多數(shù)系統(tǒng)書籍還傾向于重點(diǎn)關(guān)注系統(tǒng)的某一個方面,比如:硬件架構(gòu)、操作系統(tǒng)、編譯器或者網(wǎng)絡(luò)。本書則以程序員的視角統(tǒng)一覆蓋了上述所有方面的內(nèi)容。
如果你研究和領(lǐng)會了這本書里的概念,你將開始成為極少數(shù)的“牛人”,這些“牛人”知道事情是如何運(yùn)作的,也知道當(dāng)事情出現(xiàn)故障時如何修復(fù)。你寫的程序?qū)⒛軌蚋玫乩貌僮飨到y(tǒng)和系統(tǒng)軟件提供的功能,對各種操作條件和運(yùn)行時參數(shù)都能正確操作,運(yùn)行起來更快,并能避免出現(xiàn)使程序容易受到網(wǎng)絡(luò)攻擊的缺陷。同時,你也要做好更深入探究的準(zhǔn)備,研究像編譯器、計算機(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),單芯片上集成了更多的晶體管,這些處理器的計算能力和內(nèi)存容量有了很大的增長。在這個過程中,它們從處理16位字,發(fā)展到引入IA32處理器處理32位字,再到最近的x86-64處理64位字。
我們考慮的是這些機(jī)器如何在Linux操作系統(tǒng)上運(yùn)行C語言程序。Linux是眾多繼承自最初由貝爾實驗室開發(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ī)運(yùn)行的是Microsoft Windows系統(tǒng),我們建議你選擇安裝一個虛擬機(jī)環(huán)境(例如VirtualBox或者VMWare),以便為一種操作系統(tǒng)(客戶OS)編寫的程序能在另一種系統(tǒng)(宿主OS)上運(yùn)行。
我們還假設(shè)你對C和C++有一定的了解。如果你以前只有Java經(jīng)驗,那么你需要付出更多的努力來完成這種轉(zhuǎn)換,不過我們也會幫助你。Java和C有相似的語法和控制語句。不過,有一些C語言的特性(特別是指針、顯式的動態(tài)內(nèi)存分配和格式化I/O)在Java中都是沒有的。所幸的是,C是一個較小的語言,在Brian Kernighan和Dennis Ritchie經(jīng)典的“K&R”文獻(xiàn)中得到了清晰優(yōu)美的描述\[61\]。無論你的編程背景如何,都應(yīng)該考慮將K&R作為個人系統(tǒng)藏書的一部分。如果你只有使用解釋性語言的經(jīng)驗,如Python、Ruby或Perl,那么在使用本書之前,需要花費(fèi)一些時間來學(xué)習(xí)C。
本書的前幾章揭示了C語言程序和它們相對應(yīng)的機(jī)器語言程序之間的交互作用。機(jī)器語言示例都是用運(yùn)行在x86-64處理器上的GNU GCC編譯器生成的。我們不需要你以前有任何硬件、機(jī)器語言或是匯編語言編程的經(jīng)驗。
給C語言初學(xué)者 關(guān)于C編程語言的建議
為了幫助C語言編程背景薄弱(或全無背景)的讀者,我們在書中加入了這樣一些專門的注釋來突出C中一些特別重要的特性。我們假設(shè)你熟悉C++或Java。
Randal E. Bryant,1981年于麻省理工學(xué)院獲得計算機(jī)博士學(xué)位,1984年至今一直任教于卡內(nèi)基-梅隆大學(xué),F(xiàn)任卡內(nèi)基-梅隆大學(xué)計算機(jī)科學(xué)學(xué)院院長、教授,同時還受邀任教于電子和計算機(jī)工程系。他從事本科生和研究生計算機(jī)系統(tǒng)方面課程的教學(xué)近40年。他和O’Hallaron教授一起在卡內(nèi)基梅隆大學(xué)開設(shè)了15-213課程“計算機(jī)系統(tǒng)導(dǎo)論”,那便是本書的基礎(chǔ)。他還是ACM院士、IEEE院士、美國國家工程院院士和美國人文與科學(xué)研究院院士。其研究成果被Intel、IBM、Fujitsu和Microsoft等主要計算機(jī)制造商使用,他還因研究獲得過Semiconductor Research Corporation、ACM、IEEE頒發(fā)的多項大獎。
David R. O’Hallaron卡內(nèi)基梅隆大學(xué)電子和計算機(jī)工程系教授。在弗吉尼亞大學(xué)(University of Virginia)獲得計算機(jī)科學(xué)的博士學(xué)位,2007年-2010年為Intel匹茲堡實驗室主任。他教授本科生和研究生的計算機(jī)系統(tǒng)方面的課程已有20余年,并和Bryant教授一起開設(shè)了“計算機(jī)系統(tǒng)導(dǎo)論”課程。曾獲得CMU計算機(jī)學(xué)院頒發(fā)的Herbert Simon杰出教學(xué)獎。他主要從事計算機(jī)系統(tǒng)領(lǐng)域的研究,與Quake項目成員一起獲得過高性能計算領(lǐng)域中的*高國際獎項——Gordon Bell獎。他目前的工作重點(diǎn)是研究自動分級(autograding)概念,即評價其他程序質(zhì)量的程序。
目錄
出版者的話
中文版序一
中文版序二
譯者序
前言
關(guān)于作者
第1章 計算機(jī)系統(tǒng)漫游1
1.1 信息就是位+上下文1
1.2 程序被其他程序翻譯成不同的格式3
1.3 了解編譯系統(tǒng)如何工作是大有益處的4
1.4 處理器讀并解釋儲存在內(nèi)存中的指令5
1.4.1 系統(tǒng)的硬件組成5
1.4.2 運(yùn)行hello程序7
1.5 高速緩存至關(guān)重要9
1.6 存儲設(shè)備形成層次結(jié)構(gòu)9
1.7 操作系統(tǒng)管理硬件10
1.7.1 進(jìn)程11
1.7.2 線程12
1.7.3 虛擬內(nèi)存12
1.7.4 文件14
1.8 系統(tǒng)之間利用網(wǎng)絡(luò)通信14
1.9 重要主題16
1.9.1 Amdahl定律16
1.9.2 并發(fā)和并行17
1.9.3 計算機(jī)系統(tǒng)中抽象的重要性19
1.10 小結(jié)20
參考文獻(xiàn)說明20
練習(xí)題答案20
第一部分
程序結(jié)構(gòu)和執(zhí)行
第2章 信息的表示和處理22
2.1 信息存儲24
2.1.1 十六進(jìn)制表示法25
2.1.2 字?jǐn)?shù)據(jù)大小27
2.1.3 尋址和字節(jié)順序29
2.1.4 表示字符串34
2.1.5 表示代碼34
2.1.6 布爾代數(shù)簡介35
2.1.7 C語言中的位級運(yùn)算37
2.1.8 C語言中的邏輯運(yùn)算39
2.1.9 C語言中的移位運(yùn)算40
2.2 整數(shù)表示41
2.2.1 整型數(shù)據(jù)類型42
2.2.2 無符號數(shù)的編碼43
2.2.3 補(bǔ)碼編碼44
2.2.4 有符號數(shù)和無符號數(shù)之間的轉(zhuǎn)換49
2.2.5 C語言中的有符號數(shù)與無符號數(shù)52
2.2.6 擴(kuò)展一個數(shù)字的位表示54
2.2.7 截斷數(shù)字56
2.2.8 關(guān)于有符號數(shù)與無符號數(shù)的建議58
2.3 整數(shù)運(yùn)算60
2.3.1 無符號加法60
2.3.2 補(bǔ)碼加法62
2.3.3 補(bǔ)碼的非66
2.3.4 無符號乘法67
2.3.5 補(bǔ)碼乘法67
2.3.6 乘以常數(shù)70
2.3.7 除以2的冪71
2.3.8 關(guān)于整數(shù)運(yùn)算的最后思考74
2.4 浮點(diǎn)數(shù)75
2.4.1 二進(jìn)制小數(shù)76
2.4.2 IEEE浮點(diǎn)表示78
2.4.3 數(shù)字示例79
2.4.4 舍入83
2.4.5 浮點(diǎn)運(yùn)算85
2.4.6 C語言中的浮點(diǎn)數(shù)86
2.5 小結(jié)87
參考文獻(xiàn)說明88
家庭作業(yè)88
練習(xí)題答案97
第3章 程序的機(jī)器級表示109
3.1 歷史觀點(diǎn)110
3.2 程序編碼113
3.2.1 機(jī)器級代碼113
3.2.2 代碼示例114
3.2.3 關(guān)于格式的注解117
3.3 數(shù)據(jù)格式119
3.4 訪問信息119
3.4.1 操作數(shù)指示符121
3.4.2 數(shù)據(jù)傳送指令122
3.4.3 數(shù)據(jù)傳送示例125
3.4.4 壓入和彈出棧數(shù)據(jù)127
3.5 算術(shù)和邏輯操作128
3.5.1 加載有效地址129
3.5.2 一元和二元操作130
3.5.3 移位操作131
3.5.4 討論131
3.5.5 特殊的算術(shù)操作133
3.6 控制135
3.6.1 條件碼135
3.6.2 訪問條件碼136
3.6.3 跳轉(zhuǎn)指令138
3.6.4 跳轉(zhuǎn)指令的編碼139
3.6.5 用條件控制來實現(xiàn)條件分支…141
3.6.6 用條件傳送來實現(xiàn)條件分支…145
3.6.7 循環(huán)149
3.6.8 switch語句159
3.7 過程164
3.7.1 運(yùn)行時棧164
3.7.2 轉(zhuǎn)移控制165
3.7.3 數(shù)據(jù)傳送168
3.7.4 棧上的局部存儲170
3.7.5 寄存器中的局部存儲空間172
3.7.6 遞歸過程174
3.8 數(shù)組分配和訪問176
3.8.1 基本原則176
3.8.2 指針運(yùn)算177
3.8.3 嵌套的數(shù)組178
3.8.4 定長數(shù)組179
3.8.5 變長數(shù)組181
3.9 異質(zhì)的數(shù)據(jù)結(jié)構(gòu)183
3.9.1 結(jié)構(gòu)183
3.9.2 聯(lián)合186
3.9.3 數(shù)據(jù)對齊189
3.10 在機(jī)器級程序中將控制與數(shù)據(jù)結(jié)合起來192
3.10.1 理解指針192
3.10.2 應(yīng)用:使用GDB調(diào)試器193
3.10.3 內(nèi)存越界引用和緩沖區(qū)溢出194
3.10.4 對抗緩沖區(qū)溢出攻擊198
3.10.5 支持變長棧幀201
3.11 浮點(diǎn)代碼204
3.11.1 浮點(diǎn)傳送和轉(zhuǎn)換操作205
3.11.2 過程中的浮點(diǎn)代碼209
3.11.3 浮點(diǎn)運(yùn)算操作210
3.11.4 定義和使用浮點(diǎn)常數(shù)212
3.11.5 在浮點(diǎn)代碼中使用位級操作212
3.11.6 浮點(diǎn)比較操作213
3.11.7 對浮點(diǎn)代碼的觀察結(jié)論215
3.12 小結(jié)216
參考文獻(xiàn)說明216
家庭作業(yè)216
練習(xí)題答案226
第4章 處理器體系結(jié)構(gòu)243
4.1 Y86-64指令集體系結(jié)構(gòu)245
4.1.1 程序員可見的狀態(tài)245
4.1.2 Y86-64指令245
4.1.3 指令編碼246
4.1.4 Y86-64異常250
4.1.5 Y86-64程序251
4.1.6 一些Y86-64指令的詳情255
4.2 邏輯設(shè)計和硬件控制語言HCL256
4.2.1 邏輯門257
4.2.2 組合電路和HCL布爾表達(dá)式257
4.2.3 字級的組合電路和HCL整數(shù)表達(dá)式258
4.2.4 集合關(guān)系261
4.2.5 存儲器和時鐘262
4.3 Y86-64的順序?qū)崿F(xiàn)264
4.3.1 將處理組織成階段264
4.3.2 SEQ硬件結(jié)構(gòu)272
4.3.3 SEQ的時序274
4.3.4 SEQ階段的實現(xiàn)277
4.4 流水線的通用原理282
4.4.1 計算流水線282
4.4.2 流水線操作的詳細(xì)說明284
4.4.3 流水線的局限性284
4.4.4 帶反饋的流水線系統(tǒng)287