計算機底層的秘密

計算機底層的秘密

《計算機底層的秘密》是電子工業出版社出版的圖書,作者是陸小風。

網際網路大廠專家為你揭示編程高手的心智模型和計算機系統的底層奧秘,341幅精心設計的插圖把對技術的理解門檻儘量降低。

像高手那樣,對自己寫下的每一行代碼到底會對計算機系統產生怎樣的影響了如指掌,遇到問題瞬間解決。

基本介紹

  • 中文名:計算機底層的秘密
  • 作者:陸小風
  • 出版時間:2023年4月
  • 出版社:電子工業出版社
  • 頁數:324 頁
  • ISBN:9787121452772
  • 定價:118.00 元
  • 開本:16 開
內容簡介,圖書目錄,作者簡介,

內容簡介

《計算機底層的秘密》以圖解的方式通俗易懂地講解計算機系統中各項技術的本質,包括程式語言的本質是什麼、作業系統、進程執行緒協程等的本質是什麼、到底什麼是記憶體、什麼是堆區棧區、記憶體分配等是怎么一回事、怎樣從電晶體構建出CPU、I/O是如何實現的等等,從根源出發,一步步講解一項技術到底是怎么來的,同時內容可視化——輔助大量精心設計的插圖,幾乎做到了平均一頁有一圖,把對技術的理解門檻儘量降低。

圖書目錄

第1章 從程式語言到可執行程式,這是怎么一回事 / 1
1.1 假如你來發明程式語言 / 2
1.1.1 創世紀: CPU是個聰明的笨蛋 / 3
1.1.2 彙編語言出現了 / 3
1.1.3 底層的細節 vs 高層的抽象 / 4
1.1.4 套路滿滿:高級程式語言的雛形 / 6
1.1.5 《盜夢空間》與遞歸:代碼的本質 / 7
1.1.6 讓計算機理解遞歸 / 9
1.1.7 優秀的翻譯官:編譯器 / 9
1.1.8 解釋型語言的誕生 / 10
1.2 編譯器是如何工作的 / 12
1.2.1 編譯器就是一個普通程式,沒什麼大不了的 / 12
1.2.2 提取出每一個符號 / 13
1.2.3 token 想表達什麼含義 / 14
1.2.4 語法樹是不是合理的 / 14
1.2.5 根據語法樹生成中間代碼 / 15
1.2.6 代碼生成 / 15
1.3 連結器不能說的秘密 / 16
1.3.1 連結器是如何工作的 / 17
1.3.2 符號決議:供給與需求 / 18
1.3.3 靜態庫、動態庫與執行檔 / 20
1.3.4 動態庫有哪些優勢及劣勢 / 25
1.3.5 重定位:確定符號運行時地址 / 27
1.3.6 虛擬記憶體與程式記憶體布局 / 29
1.4 為什麼抽象在計算機科學中如此重要 / 32
1.4.1 編程與抽象 / 32
1.4.2 系統設計與抽象 / 33
1.5 總結 / 34
第2章 程式運行起來了,可我對其一無所知 / 35
2.1 從根源上理解作業系統、進程與執行緒 / 36
2.1.1 一切要從 CPU說起 / 36
2.1.2 從 CPU到作業系統 / 37
2.1.3 進程很好,但還不夠方便 / 40
2.1.4 從進程演變到執行緒 / 41
2.1.5 多執行緒與記憶體布局 / 44
2.1.6 執行緒的使用場景 / 44
2.1.7 執行緒池是如何工作的 / 45
2.1.8 執行緒池中執行緒的數量 / 46
2.2 執行緒間到底共享了哪些進程資源 / 47
2.2.1 執行緒私有資源 / 47
2.2.2 代碼區:任何函式都可放到執行緒中執行 / 49
2.2.3 數據區:任何執行緒均可訪問數據區變數 / 49
2.2.4 堆區:指針是關鍵 / 50
2.2.5 棧區:公共的私有數據 / 50
2.2.6 動態程式庫與檔案 / 52
2.2.7 執行緒局部存儲: TLS / 53
2.3 執行緒安全代碼到底是怎么編寫的 / 55
2.3.1 自由與約束 / 55
2.3.2 什麼是執行緒安全 / 56
2.3.3 執行緒的私有資源與共享資源 / 57
2.3.4 只使用執行緒私有資源 / 58
2.3.5 執行緒私有資源 + 函式參數 / 58
2.3.6 使用全局變數 / 60
2.3.7 執行緒局部存儲 / 61
2.3.8 函式返回值 / 62
2.3.9 調用非執行緒安全代碼 / 63
2.3.10 如何實現執行緒安全代碼 / 64
2.4 程式設計師應如何理解協程 / 65
2.4.1 普通的函式 / 65
2.4.2 從普通函式到協程 / 66
2.4.3 協程的圖形化解釋 / 68
2.4.4 函式只是協程的一種特例 / 69
2.4.5 協程的歷史 / 69
2.4.6 協程是如何實現的 / 70
2.5 徹底理解回調函式 / 71
2.5.1 一切要從這樣的需求說起 / 72
2.5.2 為什麼需要回調 / 73
2.5.3 異步回調 / 74
2.5.4 異步回調帶來新的編程思維 / 75
2.5.5 回調函式的定義 / 77
2.5.6 兩種回調類型 / 78
2.5.7 異步回調的問題:回調地獄 / 79
2.6 徹底理解同步與異步 / 80
2.6.1 辛苦的程式設計師 / 80
2.6.2 打電話與發郵件 / 81
2.6.3 同步調用 / 83
2.6.4 異步調用 / 84
2.6.5 同步、異步在網路伺服器中的套用 / 86
2.7 喔!對了,還有阻塞與非阻塞 / 91
2.7.1 阻塞與非阻塞 / 92
2.7.2 阻塞的核心問題: I/O / 92
2.7.3 非阻塞與異步 I/O / 93
2.7.4 一個類比:點比薩 / 94
2.7.5 同步與阻塞 / 95
2.7.6 異步與非阻塞 / 96
2.8 融會貫通:高並發、高性能伺服器是如何實現的 / 97
2.8.1 多進程 / 97
2.8.2 多執行緒 / 98
2.8.3 事件循環與事件驅動 / 99
2.8.4 問題 1 :事件來源與 I/O 多路復用 / 100
2.8.5 問題 2:事件循環與多執行緒 / 101
2.8.6 咖啡館是如何運作的: Reactor 模式 / 102
2.8.7 事件循環與 I/O / 103
2.8.8 異步與回調函式 / 103
2.8.9 協程:以同步的方式進行異步編程 / 106
2.8.10 CPU、執行緒與協程 / 107
2.9 計算機系統漫遊:從數據、代碼、回調、閉包到容器、虛擬機 / 108
2.9.1 代碼、數據、變數與指針 / 108
2.9.2 回調函式與閉包 / 110
2.9.3 容器與虛擬機技術 / 112
2.10 總結 / 114
第3章 底層?就從記憶體這個儲物櫃開始吧 / 115
3.1 記憶體的本質、指針及引用 / 116
3.1.1 記憶體的本質是什麼?儲物櫃、比特、位元組與對象 / 116
3.1.2 從記憶體到變數:變數意味著什麼 / 117
3.1.3 從變數到指針:如何理解指針 / 120
3.1.4 指針的威力與破壞性:能力與責任 / 122
3.1.5 從指針到引用:隱藏記憶體地址 / 123
3.2 進程在記憶體中是什麼樣子的 / 124
3.2.1 虛擬記憶體:眼見未必為實 / 125
3.2.2 頁與頁表:從虛幻到現實 / 125
3.3 棧區:函式調用是如何實現的 / 127
3.3.1 程式設計師的好幫手:函式 / 128
3.3.2 函式調用的活動軌跡:棧 / 128
3.3.3 棧幀與棧區:以巨觀的角度看 / 130
3.3.4 函式跳轉與返回是如何實現的 / 131
3.3.5 參數傳遞與返回值是如何實現的 / 133
3.3.6 局部變數在哪裡 / 134
3.3.7 暫存器的保存與恢復 / 134
3.3.8 Big Picture:我們在哪裡 / 134
3.4 堆區:記憶體動態分配是如何實現的 / 136
3.4.1 為什麼需要堆區 / 136
3.4.2 自己動手實現一個 malloc 記憶體分配器 / 137
3.4.3 從停車場到記憶體管理 / 138
3.4.4 管理空閒記憶體塊 / 139
3.4.5 跟蹤記憶體分配狀態 / 141
3.4.6 怎樣選擇空閒記憶體塊:分配策略 / 142
3.4.7 分配記憶體 / 144
3.4.8 釋放記憶體 / 146
3.4.9 高效合併空閒記憶體塊 / 149
3.5 申請記憶體時底層發生了什麼 / 150
3.5.1 三界與 CPU運行狀態 / 150
3.5.2 核心態與用戶態 / 151
3.5.3 傳送門:系統調用 / 152
3.5.4 標準庫:禁止系統差異 / 153
3.5.5 堆區記憶體不夠了怎么辦 / 154
3.5.6 向作業系統申請記憶體: brk / 155
3.5.7 冰山之下:虛擬記憶體才是終極 BOSS / 156
3.5.8 關於分配記憶體完整的故事 / 156
3.6 高性能伺服器記憶體池是如何實現的 / 157
3.6.1 記憶體池 vs 通用記憶體分配器 / 158
3.6.2 記憶體池技術原理 / 158
3.6.3 實現一個極簡記憶體池 / 159
3.6.4 實現一個稍複雜的記憶體池 / 160
3.6.5 記憶體池的執行緒安全問題 / 161
3.7 與記憶體相關的經典 bug / 162
3.7.1 返回指向局部變數的指針 / 163
3.7.2 錯誤地理解指針運算 / 163
3.7.3 解引用有問題的指針 / 164
3.7.4 讀取未被初始化的記憶體 / 165
3.7.5 引用已被釋放的記憶體 / 166
3.7.6 數組下標是從 0 開始的 / 167
3.7.7 棧溢出 / 167
3.7.8 記憶體泄漏 / 168
3.8 為什麼 SSD 不能被當成記憶體用 / 169
3.8.1 記憶體讀寫與硬碟讀寫的區別 / 169
3.8.2 虛擬記憶體的限制 / 171
3.8.3 SSD 的使用壽命問題 / 171
3.9 總結 / 171
第4章 從電晶體到 CPU,誰能比我更重要 / 173
4.1 你管這破玩意叫 CPU / 174
4.1.1 偉大的發明 / 174
4.1.2 與、或、非: AND 、OR、NOT / 174
4.1.3 道生一、一生二、二生三、三生萬物 / 175
4.1.4 計算能力是怎么來的 / 175
4.1.5 神奇的記憶能力 / 176
4.1.6 暫存器與記憶體的誕生 / 177
4.1.7 硬體還是軟體?通用設備 / 178
4.1.8 硬體的基本功:機器指令 / 179
4.1.9 軟體與硬體的接口:指令集 / 179
4.1.10 指揮家,讓我們演奏一曲 / 180
4.1.11 大功告成,CPU誕生了 / 180
4.2 CPU空閒時在幹嗎 / 181
4.2.1 你的計算機 CPU使用率是多少 / 181
4.2.2 進程管理與進程調度 / 182
4.2.3 佇列判空:一個更好的設計 / 183
4.2.4 一切都要歸結到 CPU / 184
4.2.5 空閒進程與 CPU低功耗狀態 / 184
4.2.6 逃出無限循環:中斷 / 185
4.3 CPU是如何識數的 / 186
4.3.1 數字 0 與正整數 / 186
4.3.2 有符號整數 / 187
4.3.3 正數加上負號即對應的負數:原碼 / 187
4.3.4 原碼的翻轉:反碼 / 188
4.3.5 不簡單的兩數相加 / 188
4.3.6 對計算機友好的表示方法:補碼 / 189
4.3.7 CPU真的識數嗎 / 191
4.4 當 CPU遇上 if語句 / 192
4.4.1 流水線技術的誕生 / 193
4.4.2 CPU——超級工廠與流水線 / 195
4.4.3 當 if 遇到流水線 / 196
4.4.4 分支預測:儘量讓 CPU猜對 / 197
4.5 CPU核數與執行緒數有什麼關係 / 199
4.5.1 菜譜與代碼、炒菜與執行緒 / 199
4.5.2 任務拆分與阻塞式 I/O / 200
4.5.3 多核與多執行緒 / 201
4.6 CPU進化論(上):複雜指令集誕生 / 202
4.6.1 程式設計師眼裡的CPU / 202
4.6.2 CPU的能力圈:指令集 / 202
4.6.3 抽象:少就是多 / 203
4.6.4 代碼也是要占用存儲空間的 / 203
4.6.5 複雜指令集誕生的必然 / 205
4.6.6 微代碼設計的問題 / 205
4.7 CPU進化論(中):精簡指令集的誕生 / 206
4.7.1 化繁為簡 / 206
4.7.2 精簡指令集哲學 / 207
4.7.3 CISC 與 RISC 的區別 / 208
4.7.4 指令流水線 / 209
4.7.5 名揚天下 / 210
4.8 CPU進化論(下):絕地反擊 / 211
4.8.1 打不過就加入:像 RISC 一樣的CISC / 211
4.8.2 超執行緒的絕技 / 212
4.8.3 取人之長,補己之短: CISC 與 RISC 的融合 / 214
4.8.4 技術不是全部: CISC 與 RISC 的商業之戰 / 214
4.9 融會貫通:CPU、棧與函式調用、系統調用、執行緒切換、中斷處理/ 215
4.9.1 暫存器 / 215
4.9.2 棧暫存器: Stack Pointer / 216
4.9.3 指令地址暫存器: ProgramCounter / 216
4.9.4 狀態暫存器: StatusRegister / 217
4.9.5 上下文: Context / 218
4.9.6 嵌套與棧 / 218
4.9.7 函式調用與運行時棧 / 220
4.9.8 系統調用與核心態棧 / 220
4.9.9 中斷與中斷函式棧 / 223
4.9.10 執行緒切換與核心態棧 / 224
4.10 總結 / 227
第5章 四兩撥千斤,cache / 228
5.1 cache,無處不在 / 229
5.1.1 CPU與記憶體的速度差異 / 229
5.1.2 圖書館、書桌與 cache / 230
5.1.3 天下沒有免費的午餐: cache 更新 / 232
5.1.4 天下也沒有免費的晚餐:多核 cache 一致性 / 233
5.1.5 記憶體作為磁碟的cache / 235
5.1.6 虛擬記憶體與磁碟 / 237
5.1.7 CPU是如何讀取記憶體的 / 238
5.1.8 分散式存儲來幫忙 / 238
5.2 如何編寫對cache 友好的程式 / 240
5.2.1 程式的局部性原理 / 240
5.2.2 使用記憶體池 / 241
5.2.3 struct 結構體重新布局 / 241
5.2.4 冷熱數據分離 / 242
5.2.5 對 cache 友好的數據結構 / 243
5.2.6 遍歷多維數組 / 243
5.3 多執行緒的性能“殺手” / 245
5.3.1 cache 與記憶體互動的基本單位: cacheline / 246
5.3.2 性能“殺手”一: cache 桌球問題 / 247
5.3.3 性能“殺手”二:偽共享問題 / 250
5.4 烽火戲諸侯與記憶體屏障 / 253
5.4.1 指令亂序執行:編譯器與 OoOE / 255
5.4.2 把 cache 也考慮進來 / 257
5.4.3 四種記憶體屏障類型 / 259
5.4.4 acquire-release 語義 / 263
5.4.5 C++ 中提供的接口 / 264
5.4.6 不同的CPU,不同的秉性 / 265
5.4.7 誰應該關心指令重排序:無鎖編程 / 266
5.4.8 有鎖編程 vs 無鎖編程 / 267
5.4.9 關於指令重排序的爭議 / 267
5.5 總結 / 268
第6章 計算機怎么能少得了 I/O / 269
6.1 CPU是如何處理 I/O 操作的 / 270
6.1.1 專事專辦: I/O 機器指令 / 270
6.1.2 記憶體映射 I/O / 270
6.1.3 CPU讀寫鍵盤的本質 / 271
6.1.4 輪詢:一遍遍地檢查 / 272
6.1.5 點外賣與中斷處理 / 273
6.1.6 中斷驅動式 I/O / 274
6.1.7 CPU如何檢測中斷信號 / 275
6.1.8 中斷處理與函式調用的區別 / 276
6.1.9 保存並恢復被中斷程式的執行狀態 / 277
6.2 磁碟處理I/O 時 CPU在幹嗎 / 279
6.2.1 設備控制器 / 280
6.2.2 CPU應該親自複製數據嗎 / 281
6.2.3 直接存儲器訪問: DMA / 281
6.2.4 Put Together / 283
6.2.5 對程式設計師的啟示 / 284
6.3 讀取檔案時程式經歷了什麼 / 285
6.3.1 從記憶體的角度看 I/O / 285
6.3.2 read 函式是如何讀取檔案的 / 286
6.4 高並發的秘訣:I/O 多路復用 / 291
6.4.1 檔案描述符 / 291
6.4.2 如何高效處理多個 I/O / 292
6.4.3 不要打電話給我,有必要我會打給你 / 293
6.4.4 I/O 多路復用 / 294
6.4.5 三劍客: select 、poll 與 epoll / 294
6.5 mmap:像讀寫記憶體那樣操作檔案 / 295
6.5.1 檔案與虛擬記憶體 / 296
6.5.2 魔術師作業系統 / 297
6.5.3 mmap vs 傳統 read/write 函式 / 298
6.5.4 大檔案處理 / 299
6.5.5 動態程式庫與共享記憶體 / 299
6.5.6 動手操作一下 mmap / 301
6.6 計算機系統中各個部分的時延有多少 / 302
6.6.1 以時間為度量來換算 / 303
6.6.2 以距離為度量來換算 / 304
6.7 總結 / 305

作者簡介

陸小風(@碼農的荒島求生),碩士畢業於北京航空航天大學計算機學院,先後就職於VMware和京東,具有多年軟體系統研發經驗,擅長用通俗易懂的語言講解計算機技術。

相關詞條

熱門詞條

聯絡我們