1. 程式人生 > >《深入理解計算機系統(原書第2版)》pdf

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

出版者的話
譯者序
前 言
第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