深入理解計算機系統(原書第2版)

深入理解計算機系統(原書第2版)

《深入理解計算機系統(原書第2版)》是2010年機械工業出版社出版的圖書,作者是Randal E.Bryant、David R.O’Hallaron。

基本信息

內容簡介

本書從程式設計師的視角詳細闡述計算機系統的本質概念,並展示這些概念如何實實在在地影回響用程式的正確性、性能和實用性。全書共12章,主要內容包括信息的表示和處理、程式的機器級表示、處理器體系結構、最佳化程式性能、存儲器層次結構、連結、異常控制流、虛擬存儲器、系統級I/O、網路編程、並發編程等。書中提供大量的例子和練習,並給出部分答案,有助於讀者加深對正文所述概念和知識的理解。

通過掌握程式是如何映射到系統上,以及程式是如何執行的,讀者能夠更好地理解程式的行為為什麼是這樣的,以及效率低下是如何造成的。

本書適合那些想要寫出更快、更可靠程式的程式設計師閱讀,也適合作為高等院校計算機及相關專業本科生、研究生的教材。

本書的最大優點是為程式設計師描述計算機系統的實現細節,幫助其在大腦中構造一個層次型的計算機系統,從最底層的數據在記憶體中的表示到流水線指令的構成,到虛擬存儲器,到編譯系統,到動態載入庫,到最後的用戶態套用。

作者簡介

Randal E.Bryant 1973年於密西根大學(University of Michigan)獲得學士學位,隨即就讀於麻省理工學院的研究生院,並在1981年獲計算機博士學位。他在加州理工學院(California Institute of Technology)做了三年助教,從1984年至今一直是卡內基-梅隆大學的教師。他現在是計算機科學的大學教授和計算機科學學院的院長。他同時還受邀於電子和計算機工程系。

他從事本科生和研究生計算機系統方面課程的教學超過30年。在講授計算機體系結構課程多年後,他開始把關注點從如何設計計算機轉移到程式設計師如何在更好的了解系統的情況下編寫出更有效和更可靠的程式。他和O’Hallaron教授一起在卡內基梅隆大學開設了15-213“計算機系統導論”課程,那便是此書的基礎。他還教授一些有關算法、編程、計算機網路和VLSI(超大規模積體電路)設計方面的課程。

Bryant教授的主要研究內容是設計軟體工具來幫助軟體和硬體設計者驗證其系統正確性。其中,包括幾種類型的模擬器,以及用數學方法來證明設計正確性的形式化驗證工具。他發表了150多篇技術論文。包括Intel、FreeScale、IBM和Fujitsu在內的主要計算機製造商都使用著他的研究成果。他還因他的研究獲得過數項大獎。其中包括Semiconductor Research Corporation頒發的兩個發明榮譽獎和一個技術成就獎,ACM頒發的Kanellakis理論與實踐獎,還有IEEE授予的W.R.G.Baker獎、Emmanuel Piore獎和Phil Kaufman獎。他還是ACM院士、IEEE院士和美國國家工程院院士。

David R.O’Hallaron 現為Intel匹茲堡實驗室主任,卡內基-梅隆大學電子和計算機工程系副教授。在維吉尼亞大學獲得計算機科學的博士學位。

他教授本科生和研究生的計算機系統方面的課程,例如計算機體系結構、計算機系統導論、並行處理器設計和Internet服務。他和Bryant教授一起開設了“計算機系統導論”課程,那便是此書的基礎。2004年他獲得了CMU計算機學院頒發的Herbert Simon傑出教學獎,這個獎項的獲得者是基於學生的投票產生的。

O’Hallaron教授從事計算機系統領域的研究,主要興趣在於科學計算、數據密集型計算和虛擬化方面的軟體系統。其中最著名的是Quake項目,一群計算機科學家、土木工程師和地震學家致力於提高對強烈地震中大地運動的預測能力。2003年,他同Quake項目中其他成員一起獲得了高性能計算領域中的最高國際獎項—Gordon Bell獎。

英文版

英文版封面 英文版封面

叢書名:經典原版書庫書號:978-7-111-32631-1

定價:128.00元

圖書目錄

出版者的話

譯者序

前 言

第1章 計算機系統漫遊1

1.1 信息就是位+上下文1

1.2 程式被其他程式翻譯成不同的格式3

1.3 了解編譯系統如何工作是大有益處的4

1.4 處理器讀並解釋存儲在存儲器中的指令5

1.4.1 系統的硬體組成5

1.4.2 運行hello程式7

1.5 高速快取至關重要7

1.6 存儲設備形成層次結構9

1.7 作業系統管理硬體10

1.7.1 進程11

1.7.2 執行緒12

1.7.3 虛擬存儲器12

1.7.4 檔案13

1.8 系統之間利用網路通信13

1.9 重要主題15

1.9.1 並發和並行15

1.9.2 計算機系統中抽象的重要性17

1.10 小結17

參考文獻說明18

第一部分 程式結構和執行

第2章 信息的表示和處理20

2.1 信息存儲22

2.1.1 十六進制表示法22

2.1.2 字25

2.1.3 數據大小25

2.1.4 定址和位元組順序26

2.1.5 表示字元串31

2.1.6 表示代碼31

2.1.7 布爾代數簡介32

2.1.8 C語言中的位級運算34

2.1.9 C語言中的邏輯運算36

2.1.10 C語言中的移位運算36

2.2 整數表示38

2.2.1 整型數據類型38

2.2.2 無符號數的編碼39

2.2.3 補碼編碼40

2.2.4 有符號數和無符號數之間的轉換44

2.2.5 C語言中的有符號數與無符號數47

2.2.6 擴展一個數字的位表示49

2.2.7 截斷數字51

2.2.8 關於有符號數與無符號數的建議52

2.3 整數運算54

2.3.1 無符號加法54

2.3.2 補碼加法57

2.3.3 補碼的非59

2.3.4 無符號乘法60

2.3.5 補碼乘法60

2.3.6 乘以常數63

2.3.7 除以2的冪64

2.3.8 關於整數運算的最後思考67

2.4 浮點數67

2.4.1 二進制小數68

2.4.2 IEEE浮點表示70

2.4.3 數字示例71

2.4.4 捨入74

2.4.5 浮點運算76

2.4.6 C語言中的浮點數77

2.5 小結79

參考文獻說明80

家庭作業80

練習題答案90

第3章 程式的機器級表示102

3.1 歷史觀點103

3.2 程式編碼105

3.2.1 機器級代碼106

3.2.2 代碼示例107

3.2.3 關於格式的註解109

3.3 數據格式111

3.4 訪問信息112

3.4.1 運算元指示符112

3.4.2 數據傳送指令114

3.4.3 數據傳送示例116

3.5 算術和邏輯操作118

3.5.1 載入有效地址118

3.5.2 一元操作和二元操作119

3.5.3 移位操作120

3.5.4 討論120

3.5.5 特殊的算術操作122

3.6 控制123

3.6.1 條件碼124

3.6.2 訪問條件碼125

3.6.3 跳轉指令及其編碼127

3.6.4 翻譯條件分支129

3.6.5 循環132

3.6.6 條件傳送指令139

3.6.7 switch語句144

3.7 過程149

3.7.1 棧幀結構149

3.7.2 轉移控制150

3.7.3 暫存器使用慣例151

3.7.4 過程示例152

3.7.5 遞歸過程156

3.8 數組分配和訪問158

3.8.1 基本原則158

3.8.2 指針運算159

3.8.3 嵌套的數組159

3.8.4 定長數組161

3.8.5 變長數組163

3.9 異質的數據結構164

3.9.1 結構164

3.9.2 聯合167

3.9.3 數據對齊170

3.10 綜合:理解指針172

3.11 套用:使用GDB調試器174

3.12 存儲器的越界引用和緩衝區溢出175

3.13 x86-64:將IA32擴展到64位183

3.13.1 x86-64的歷史和動因184

3.13.2 x86-64簡介185

3.13.3 訪問信息187

3.13.4 控制192

3.13.5 數據結構200

3.13.6 關於x86-64的總結性評論200

3.14 浮點程式的機器級表示201

3.15 小結201

參考文獻說明202

家庭作業202

練習題答案212

第4章 處理器體系結構230

4.1 Y86指令集體系結構231

4.1.1 程式設計師可見的狀態231

4.1.2 Y86指令232

4.1.3 指令編碼233

4.1.4 Y86異常237

4.1.5 Y86程式237

4.1.6 一些Y86指令的詳情241

4.2 邏輯設計和硬體控制語言HCL242

4.2.1 邏輯門243

4.2.2 組合電路和HCL布爾表達式243

4.2.3 字級的組合電路和HCL整數表達式245

4.2.4 集合關係248

4.2.5 存儲器和時鐘248

4.3 Y86的順序實現250

4.3.1 將處理組織成階段250

4.3.2 SEQ硬體結構258

4.3.3 SEQ的時序259

4.3.4 SEQ階段的實現262

4.4 流水線的通用原理267

4.4.1 計算流水線268

4.4.2 流水線操作的詳細說明269

4.4.3 流水線的局限性271

4.4.4 帶反饋的流水線系統272

4.5 Y86的流水線實現273

4.5.1 SEQ+:重新安排計算階段273

4.5.2 插入流水線暫存器276

4.5.3 對信號進行重新排列和標號277

4.5.4 預測下一個PC279

4.5.5 流水線冒險280

4.5.6 用暫停來避免數據冒險283

4.5.7 用轉發來避免數據冒險285

4.5.8 載入/使用數據冒險288

4.5.9 異常處理289

4.5.10 PIPE各階段的實現291

4.5.11 流水線控制邏輯297

4.5.12 性能分析305

4.5.13 未完成的工作306

4.6 小結308

參考文獻說明309

家庭作業309

練習題答案314

第5章 最佳化程式性能324

5.1 最佳化編譯器的能力和局限性325

5.2 表示程式性能328

5.3 程式示例330

5.4 消除循環的低效率332

5.5 減少過程調用336

5.6 消除不必要的存儲器引用336

5.7 理解現代處理器340

5.7.1 整體操作340

5.7.2 功能單元的性能343

5.7.3 處理器操作的抽象模型344

5.8 循環展開348

5.9 提高並行性351

5.9.1 多個累積變數351

5.9.2 重新結合變換354

5.10 最佳化合併代碼的結果小結358

5.11 一些限制因素359

5.11.1 暫存器溢出359

5.11.2 分支預測和預測錯誤處罰360

5.12 理解存儲器性能363

5.12.1 載入的性能363

5.12.2 存儲的性能364

5.13 套用:性能提高技術369

5.14 確認和消除性能瓶頸369

5.14.1 程式剖析370

5.14.2 使用剖析程式來指導最佳化371

5.14.3 Amdahl定律374

5.15 小結375

參考文獻說明375

家庭作業376

練習題答案378

第6章 存儲器層次結構382

6.1  存儲技術382

6.1.1 隨機訪問存儲器383

6.1.2 磁碟存儲389

6.1.3 固態硬碟398

6.1.4 存儲技術趨勢399

6.2 局部性401

6.2.1 對程式數據引用的局部性402

6.2.2 取指令的局部性403

6.2.3 局部性小結403

6.3 存儲器層次結構405

6.3.1 存儲器層次結構中的快取406

6.3.2 存儲器層次結構概念小結408

6.4 高速快取存儲器408

6.4.1 通用的高速快取存儲器結構409

6.4.2 直接映射高速快取410

6.4.3 組相聯高速快取416

6.4.4 全相聯高速快取418

6.4.5 有關寫的問題420

6.4.6 一個真實的高速快取層次結構的解剖421

6.4.7 高速快取參數的性能影響422

6.5 編寫高速快取友好的代碼423

6.6 綜合:高速快取對程式性能的影響426

6.6.1 存儲器山426

6.6.2 重新排列循環以提高空間局部性430

6.6.3 在程式中利用局部性433

6.7 小結433

參考文獻說明434

家庭作業434

練習題答案442

第二部分 在系統上運行程式

第7章 連結448

7.1 編譯器驅動程式449

7.2 靜態連結450

7.3 目標檔案450

7.4 可重定位目標檔案451

7.5 符號和符號表452

7.6 符號解析454

7.6.1 連結器如何解析多重定義的全局符號455

7.6.2 與靜態庫連結457

7.6.3 連結器如何使用靜態庫來解析引用460

7.7 重定位461

7.7.1 重定位條目461

7.7.2 重定位符號引用462

7.8 可執行目標檔案465

7.9 載入可執行目標檔案466

7.10 動態連結共享庫467

7.11 從應用程式中載入和連結共享庫468

7.12 與位置無關的代碼(PIC)471

7.13 處理目標檔案的工具473

7.14 小結473

參考文獻說明474

家庭作業474

練習題答案479

第8章 異常控制流480

8.1 異常481

8.1.1 異常處理481

8.1.2 異常的類別482

8.1.3 Linux/IA32系統中的異常484

8.2 進程487

8.2.1 邏輯控制流487

8.2.2 並發流487

8.2.3 私有地址空間488

8.2.4 用戶模式和核心模式488

8.2.5 上下文切換489

8.3 系統調用錯誤處理491

8.4 進程控制492

8.4.1 獲取進程ID492

8.4.2 創建和終止進程492

8.4.3 回收子進程495

8.4.4 讓進程休眠499

8.4.5 載入並運行程式500

8.4.6 利用fork和execve運行程式502

8.5 信號504

8.5.1 信號術語505

8.5.2 傳送信號506

8.5.3 接收信號509

8.5.4 信號處理問題511

8.5.5 可移植的信號處理516

8.5.6 顯式地阻塞和取消阻塞信號517

8.5.7 同步流以避免討厭的並發錯誤517

8.6 非本地跳轉521

8.7 操作進程的工具524

8.8 小結524

參考文獻說明525

家庭作業525

練習題答案530

第9章 虛擬存儲器534

9.1 物理和虛擬定址535

9.2 地址空間535

9.3 虛擬存儲器作為快取的工具536

9.3.1 DRAM快取的組織結構537

9.3.2 頁表537

9.3.3 頁命中538

9.3.4 缺頁538

9.3.5 分配頁面539

9.3.6 又是局部性救了我們539

9.4 虛擬存儲器作為存儲器管理的工具540

9.5 虛擬存儲器作為存儲器保護的工具541

9.6 地址翻譯542

9.6.1 結合高速快取和虛擬存儲器544

9.6.2 利用TLB加速地址翻譯545

9.6.3 多級頁表546

9.6.4 綜合:端到端的地址翻譯547

9.7 案例研究:Intel Core i7/Linux存儲器系統550

9.7.1 Core i7地址翻譯551

9.7.2 Linux虛擬存儲器系統554

9.8 存儲器映射556

9.8.1 再看共享對象557

9.8.2 再看fork函式558

9.8.3 再看execve函式559

9.8.4 使用mmap函式的用戶級存儲器映射559

9.9 動態存儲器分配561

9.9.1 malloc和free函式561

9.9.2 為什麼要使用動態存儲器分配563

9.9.3 分配器的要求和目標564

9.9.4 碎片565

9.9.5 實現問題565

9.9.6 隱式空閒鍊表565

9.9.7 放置已分配的塊567

9.9.8 分割空閒塊567

9.9.9 獲取額外的堆存儲器567

9.9.10 合併空閒塊568

9.9.11 帶邊界標記的合併568

9.9.12 綜合:實現一個簡單的分配器570

9.9.13 顯式空閒鍊表576

9.9.14 分離的空閒鍊表576

9.10 垃圾收集578

9.10.1 垃圾收集器的基本知識579

9.10.2 Mark&Sweep垃圾收集器580

9.10.3 C程式的保守Mark&Sweep580

9.11 C程式中常見的與存儲器有關的錯誤581

9.11.1 間接引用壞指針582

9.11.2 讀未初始化的存儲器582

9.11.3 允許棧緩衝區溢出582

9.11.4 假設指針和它們指向的對象是相同大小的583

9.11.5 造成錯位錯誤583

9.11.6 引用指針,而不是它所指向的對象583

9.11.7 誤解指針運算584

9.11.8 引用不存在的變數584

9.11.9 引用空閒堆塊中的數據584

9.11.10 引起存儲器泄漏585

9.12 小結585

參考文獻說明586

家庭作業586

練習題答案589

第三部分 程式間的互動和通信

第10章 系統級I/O596

10.1 Unix I/O596

10.2 打開和關閉檔案597

10.3 讀和寫檔案598

10.4 用RIO包健壯地讀寫599

10.4.1 RIO的無緩衝的輸入輸出函式600

10.4.2 RIO的帶緩衝的輸入函式600

10.5 讀取檔案元數據604

10.6 已分享檔案606

10.7 I/O重定向608

10.8 標準I/O609

10.9 綜合:我該使用哪些I/O函式610

10.10 小結611

參考文獻說明612

家庭作業612

練習題答案612

第11章 網路編程614

11.1 客戶端-伺服器編程模型614

11.2 網路615

11.3 全球IP網際網路618

11.3.1 IP位址619

11.3.2 網際網路域名620

11.3.3 網際網路連線623

11.4 套接字接口625

11.4.1 套接字地址結構625

11.4.2 socket函式626

11.4.3 connect函式626

11.4.4 open_clientfd函式627

11.4.5 bind函式628

11.4.6 listen函式628

11.4.7 open_listenfd函式628

11.4.8 accept函式629

11.4.9 echo客戶端和伺服器的示例630

11.5 Web伺服器633

11.5.1 Web基礎633

11.5.2 Web內容633

11.5.3 HTTP事務634

11.5.4 服務動態內容636

11.6 綜合:TINY Web伺服器639

11.7 小結645

參考文獻說明645

家庭作業646

練習題答案646

第12章 並發編程648

12.1 基於進程的並發編程649

12.1.1 基於進程的並發伺服器649

12.1.2 關於進程的優劣651

12.2 基於I/O多路復用的並發編程651

12.2.1 基於I/O多路復用的並發事件驅動伺服器653

12.2.2 I/O多路復用技術的優劣657

12.3 基於執行緒的並發編程657

12.3.1 執行緒執行模型657

12.3.2 Posix執行緒658

12.3.3 創建執行緒659

12.3.4 終止執行緒659

12.3.5 回收已終止執行緒的資源660

12.3.6 分離執行緒660

12.3.7 初始化執行緒660

12.3.8 一個基於執行緒的並發伺服器661

12.4 多執行緒程式中的共享變數662

12.4.1 執行緒存儲器模型663

12.4.2 將變數映射到存儲器663

12.4.3 共享變數664

12.5 用信號量同步執行緒664

12.5.1 進度圖667

12.5.2 信號量668

12.5.3 使用信號量來實現互斥669

12.5.4 利用信號量來調度共享資源670

12.5.5 綜合:基於預執行緒化的並發伺服器674

12.6 使用執行緒提高並行性676

12.7 其他並發問題680

12.7.1 執行緒安全680

12.7.2 可重入性682

12.7.3 線上程化的程式中使用已存在的庫函式682

12.7.4 競爭683

12.7.5 死鎖685

12.8 小結687

參考文獻說明687

家庭作業688

練習題答案691

附錄A 錯誤處理694

A.1 Unix系統中的錯誤處理694

A.2  錯誤處理包裝函式696

參考文獻698

相關詞條

相關搜尋

熱門詞條

聯絡我們