首頁 搜尋 我的知識庫
AI時代從基本功下手:深入電腦底層運作原理

AI時代從基本功下手:深入電腦底層運作原理

作者: 陸小風(@碼農的荒島求生)
出版社: 深智數位
出版日期: 2023/12/20
ISBN-13: 9786267383117
書店 1







內容描述


☆★341張圖例,一次弄懂電腦底層運作的原理★☆
☆★重點說明作業系統、處理程序、執行緒、程式碼協同底層架構★☆
☆★從前模模糊糊,似懂非懂的概念,竟然一本書就打通,全腦舒暢,寫程式每個字都知道在做什麼!★☆

  全書共分6章。

  第1章闡述了程式語言的概念和編譯器的工作原理,解釋了程式碼生成可執行程式的過程。

  第2章著重於程式執行時期,介紹了作業系統、處理程式、執行緒等概念,並強調回呼函式、同步、非同步、阻塞、非阻塞等對程式設計師的重要性。

  第3章帶領讀者認識記憶體的作用,深入探討了指標、堆積區域、堆疊區域等記憶體相關概念,並介紹了函式呼叫的實現原理和記憶體分配器的方法。

  第4章詳細介紹了電腦系統中最重要的CPU,包括其實現原理、數字識別方式和演變歷程,並解釋了複雜指令集和精簡指令集的出現原因,以及如何利用CPU和堆疊實現函式呼叫、中斷處理、執行緒切換和系統呼叫等機制。

  第5章深入講解了電腦系統中的cache,解釋了cache的必要性,並提供了程式設計師編寫cache友善程式的建議。

  第6章關注I/O(輸入輸出),介紹了電腦系統實現I/O的過程,解釋了在程式中呼叫read函式時底層的讀取過程,同時提供了高效處理I/O的建議。

  本書的特色,就是用最簡單的方式,讓程式設計師快速了解程式執行過程中底層細節的理解和心智模型,以及電腦系統的奧秘。

  現代電腦系統被層層抽象,程式設計師在高階語言中撰寫程式時不必關心底層細節,但當遇到較為複雜的問題時,對底層的理解不足會讓解決問題變得困難。而程式設計高手則能輕易解決這些問題,因為他們清楚自己的程式對電腦系統的影響,擁有深入的心智模型。

  本書通過視覺化的方式呈現內容,擁有多達341張圖片來解釋相關內容,使閱讀更加直觀易懂。同時使用通俗易懂的語言,從概念的起源開始解釋,讓讀者不僅了解是什麼和為什麼,還能理解其中的來龍去脈,降低對內容的門檻。

  這本書旨在幫助讀者建立更深入的心智模型,揭示電腦系統底層的奧秘,讓程式設計師能更有效地解決問題並提升技能水準。


目錄大綱


第1章 從程式語言到可執行程式,這是怎麼一回事
1.1 假如你來發明程式語言
1.1.1 創世紀:CPU是個聰明的笨蛋
1.1.2 組合語言出現了
1.1.3 底層的細節 vs 高層的抽象
1.1.4 策略滿滿:高級程式設計語言的雛形
1.1.5 《全面啟動》與遞迴:程式的本質
1.1.6 讓電腦理解遞迴
1.1.7 優秀的翻譯官:編譯器
1.1.8 直譯型語言的誕生
1.2 編譯器是執行原理的
1.2.1 編譯器就是一個普通程式,沒什麼大不了的
1.2.2 提取出每一個符號
1.2.3 token想表達什麼含義
1.2.4 語法樹是不是合理的
1.2.5 根據語法樹生成中間程式
1.2.6 程式生成
1.3 連結器不能說的秘密
1.3.1 連結器是運行原理的
1.3.2 符號決議:供給與需求
1.3.3 靜態程式庫、動態庫與可執行檔
1.3.4 動態庫有哪些優勢及劣勢
1.3.5 重定位:確定符號執行時期位址
1.3.6 虛擬記憶體與程式記憶體分配
1.4 為什麼抽象在電腦科學中如此重要
1.4.1 程式設計與抽象
1.4.2 系統設計與抽象
1.5 總結

第2章 程式執行起來了,可我對其一無所知
2.1 從根源上理解作業系統、處理程式與執行緒
2.1.1 一切要從CPU說起
2.1.2 從CPU到作業系統
2.1.3 處理程序很好,但還不夠方便
2.1.4 從處理程序演變到執行緒
2.1.5 多執行緒與記憶體分配
2.1.6 執行緒的使用場景
2.1.7 執行緒池是運行原理的
2.1.8 執行緒池中執行緒的數量
2.2 執行緒間到底共用了哪些處理程式資源
2.2.1 執行緒私有資源
2.2.2 程式區:任何函式都可放到執行緒中執行
2.2.3 資料區:任何執行緒均可存取資料區變數
2.2.4 堆積區域:指標是關鍵
2.2.5 堆疊區域:公共的私有資料
2.2.6 動態連結程式庫與檔案
2.2.7 執行緒局部儲存:TLS
2.3 執行緒安全程式到底是怎麼撰寫的
2.3.1 自由與約束
2.3.2 什麼是執行緒安全
2.3.3 執行緒的私有資源與共用資源
2.3.4 只使用執行緒私有資源
2.3.5 執行緒私有資源 + 函式參數
2.3.6 使用全域變數
2.3.7 執行緒局部儲存
2.3.8 函式傳回值
2.3.9 呼叫非執行緒安全程式
2.3.10 如何實現執行緒安全程式
2.4 程式設計師應如何理解程式碼協同
2.4.1 普通的函式
2.4.2 從普通函式到程式碼協同
2.4.3 程式碼協同的圖形化解釋
2.4.4 函式只是程式碼協同的一種特例
2.4.5 程式碼協同的歷史
2.4.6 程式碼協同是如何實現的
2.5 徹底理解回呼函式
2.5.1 一切要從這樣的需求說起
2.5.2 為什麼需要回呼
2.5.3 非同步回呼
2.5.4 非同步回呼帶來新的程式設計思維
2.5.5 回呼函式的定義
2.5.6 兩種回呼類型
2.5.7 非同步回呼的問題:回呼地獄
2.6 徹底理解同步與非同步
2.6.1 辛苦的程式設計師
2.6.2 打電話與發郵件
2.6.3 同步呼叫
2.6.4 非同步呼叫
2.6.5 同步、非同步在網路服務器中的應用
2.7 哦!對了,還有阻塞與非阻塞
2.7.1 阻塞與非阻塞
2.7.2 阻塞的核心問題:I/O
2.7.3 非阻塞與非同步I/O
2.7.4 一個類比:點披薩
2.7.5 同步與阻塞
2.7.6 非同步與非阻塞
2.8 融會貫通:高並行、高性能伺服器是如何實現的
2.8.1 多處理程序
2.8.2 多執行緒
2.8.3 事件迴圈與事件驅動
2.8.4 問題1:事件來源與I/O多工
2.8.5 問題2:事件迴圈與多執行緒
2.8.6 咖啡館是如何運作的:Reactor模式
2.8.7 事件迴圈與I/O
2.8.8 非同步與回呼函式
2.8.9 程式碼協同:以同步的方式進行非同步程式設計
2.8.10 CPU、執行緒與程式碼協同
2.9 電腦系統漫遊:從資料、程式、回呼、閉包到容器、虛擬機器
2.9.1 程式、資料、變數與指標
2.9.2 回呼函式與閉包
2.9.3 容器與虛擬機器技術
2.10 總結

第3章 底層?就從記憶體這個儲物櫃開始吧
3.1 記憶體的本質、指標及引用
3.1.1 記憶體的本質是什麼?儲物櫃、位元、位元組與物件
3.1.2 從記憶體到變數:變數意味著什麼
3.1.3 從變數到指標:如何理解指標
3.1.4 指標的威力與破壞性:能力與責任
3.1.5 從指標到引用:隱藏記憶體位址
3.2 處理程式在記憶體中是什麼樣子的
3.2.1 虛擬記憶體:眼見未必為實
3.2.2 分頁與分頁表:從虛幻到現實
3.3 堆疊區域:函式呼叫是如何實現的
3.3.1 程式設計師的好幫手:函式
3.3.2 函式呼叫的活動軌跡:堆疊
3.3.3 堆疊幀與堆疊區域:以宏觀的角度看
3.3.4 函式跳躍與返回是如何實現的
3.3.5 參數傳遞與傳回值是如何實現的
3.3.6 區域變數在哪裡
3.3.7 暫存器的儲存與恢復
3.3.8 Big Picture:我們在哪裡
3.4 堆積區域:記憶體動態分配是如何實現的
3.4.1 為什麼需要堆積區域
3.4.2 自己動手實現一個malloc記憶體分配器
3.4.3 從停車場到記憶體管理
3.4.4 管理空閒區塊
3.4.5 追蹤記憶體分配狀態
3.4.6 怎樣選擇空閒區塊:分配策略
3.4.7 分配記憶體
3.4.8 釋放記憶體
3.4.9 高效合併空閒區塊
3.5 申請記憶體時底層發生了什麼
3.5.1 三界與CPU運行狀態
3.5.2 核心態與使用者態
3.5.3 傳送門:系統呼叫
3.5.4 標準函式庫:遮罩系統差異
3.5.5 堆積區域記憶體不夠了怎麼辦
3.5.6 向作業系統申請記憶體:brk
3.5.7 冰山之下:虛擬記憶體才是終極BOSS
3.5.8 關於分配記憶體完整的故事
3.6 高性能伺服器記憶體池是如何實現的
3.6.1 記憶體池 vs 通用記憶體分配器
3.6.2 記憶體池技術原理
3.6.3 實現一個極簡記憶體池
3.6.4 實現一個稍複雜的記憶體池
3.6.5 記憶體池的執行緒安全問題
3.7 與記憶體相關的經典bug
3.7.1 傳回指向區域變數的指標
3.7.2 錯誤地理解指標運算
3.7.3 解引用有問題的指標
3.7.4 讀取未被初始化的記憶體
3.7.5 引用已被釋放的記憶體
3.7.6 陣列下標是從0開始的
3.7.7 堆疊溢位
3.7.8 記憶體洩漏
3.8 為什麼SSD不能被當成記憶體用
3.8.1 記憶體讀寫與硬碟讀寫的區別
3.8.2 虛擬記憶體的限制
3.8.3 SSD 的使用壽命問題
3.9 總結

第4章 從電晶體到CPU,誰能比我更重要
4.1 你管這東西叫CPU
4.1.1 偉大的發明
4.1.2 與、或、非:AND、OR、NOT
4.1.3 道生一、一生二、二生三、三生萬物
4.1.4 運算能力是怎麼來的
4.1.5 神奇的記憶能力
4.1.6 暫存器與記憶體的誕生
4.1.7 硬體還是軟體?通用裝置
4.1.8 硬體的基本功:機器指令
4.1.9 軟體與硬體的介面:指令集
4.1.10 指揮家,讓我們演奏一曲
4.1.11 大功告成,CPU誕生了
4.2 CPU 閒置時在幹嘛
4.2.1 你的電腦CPU使用率是多少
4.2.2 處理程序管理與處理程序排程
4.2.3 佇列判空:一個更好的設計
4.2.4 一切都要歸結到CPU
4.2.5 空閒處理程序與CPU低功耗狀態
4.2.6 逃出無限迴圈:中斷
4.3 CPU是如何識數的
4.3.1 數字0與正整數
4.3.2 有號整數
4.3.3 正數加上負號即對應的負數:原碼
4.3.4 原碼的翻轉:反碼
4.3.5 不簡單的兩數相加
4.3.6 對電腦友善的表示方法:補數
4.3.7 CPU真的識數嗎
4.4 當CPU遇上if語句
4.4.1 管線技術的誕生
4.4.2 CPU——超級工廠與管線
4.4.3 當if遇到管線
4.4.4 分支預測:儘量讓CPU猜對
4.5 CPU 核心數與執行緒數有什麼關係
4.5.1 食譜與程式、炒菜與執行緒
4.5.2 任務拆分與阻塞式I/O
4.5.3 多核與多執行緒
4.6 CPU 進化論(上):複雜指令集誕生
4.6.1 程式設計師眼裡的CPU
4.6.2 CPU的能力圈:指令集
4.6.3 抽象:少就是多
4.6.4 程式也是要佔用儲存空間的
4.6.5 複雜指令集誕生的必然
4.6.6 微程式設計的問題
4.7 CPU進化論(中):精簡指令集的誕生
4.7.1 化繁為簡
4.7.2 精簡指令集哲學
4.7.3 CISC與RISC的區別
4.7.4 指令管線
4.7.5 名揚天下
4.8 CPU 進化論(下):絕地反擊
4.8.1 打不過就加入:像RISC一樣的CISC
4.8.2 超執行緒的絕技
4.8.3 取人之長,補己之短:CISC與RISC的融合
4.8.4 技術不是全部:CISC與RISC的商業之戰
4.9 融會貫通:CPU、堆疊與函式呼叫、系統呼叫、執行緒切換、中斷處理
4.9.1 暫存器
4.9.2 堆疊暫存器:Stack Pointer
4.9.3 指令位址暫存器:Program Counter
4.9.4 狀態暫存器:Status Register
4.9.5 上下文:Context
4.9.6 嵌套與堆疊
4.9.7 函式呼叫與執行時期堆疊
4.9.8 系統呼叫與核心態堆疊
4.9.9 中斷與中斷函式堆疊
4.9.10 執行緒切換與核心態堆疊
4.10 總結

第5章 四兩撥千斤,cache
5.1 cache,無處不在
5.1.1 CPU 與記憶體的速度差異
5.1.2 圖書館、書桌與cache
5.1.3 天下沒有免費的午餐:cache更新
5.1.4 天下也沒有免費的晚餐:多核cache一致性
5.1.5 記憶體作為磁碟的cache
5.1.6 虛擬記憶體與磁碟
5.1.7 CPU是如何讀取記憶體的
5.1.8 分散式儲存來幫忙
5.2 如何撰寫對cache友善的程式
5.2.1 程式的局部性原理
5.2.2 使用記憶體池
5.2.3 struct結構重新佈局
5.2.4 冷熱資料分離
5.2.5 對cache友善的資料結構
5.2.6 遍歷多維陣列
5.3 多執行緒的性能「殺手」
5.3.1 cache與記憶體互動的基本單位:cache line
5.3.2 性能「殺手」一:cache乒乓問題
5.3.3 性能「殺手」二:錯誤分享問題
5.4 烽火戲諸侯與記憶體屏障
5.4.1 指令亂數執行:編譯器與OoOE
5.4.2 把cache也考慮進來
5.4.3 四種記憶體屏障類型
5.4.4 acquire-release語義
5.4.5 C++中提供的介面
5.4.6 不同的CPU,不同的秉性
5.4.7 誰應該關心指令重排序:無鎖程式設計
5.4.8 有鎖程式設計 vs 無鎖程式設計
5.4.9 關於指令重排序的爭議
5.5 總結

第6章 電腦怎麼能少得了I/O
6.1 CPU 是如何處理I/O操作的
6.1.1 專事專辦:I/O 機器指令
6.1.2 記憶體映射I/O
6.1.3 CPU讀寫鍵盤的本質
6.1.4 輪詢:一遍遍地檢查
6.1.5 點外賣與中斷處理
6.1.6 中斷驅動式I/O
6.1.7 CPU如何檢測中斷訊號
6.1.8 中斷處理與函式呼叫的區別
6.1.9 儲存並恢復被中斷程式的執行狀態
6.2 磁碟處理I/O時CPU 在幹嗎
6.2.1 裝置控制器
6.2.2 CPU應該親自複製資料嗎
6.2.3 直接記憶體存取:DMA
6.2.4 Put Together
6.2.5 對程式設計師的啟示
6.3 讀取檔案時程式經歷了什麼
6.3.1 從記憶體的角度看I/O
6.3.2 read函式是如何讀取檔案的
6.4 高並行的秘訣:I/O多工
6.4.1 檔案描述符號
6.4.2 如何高效處理多個I/O
6.4.3 不要打電話給我,有必要我會打給你
6.4.4 I/O多工
6.4.5 三劍客:select、poll與epoll
6.5 mmap:像讀寫記憶體那樣操作檔案
6.5.1 檔案與虛擬記憶體
6.5.2 魔術師作業系統
6.5.3 mmap vs 傳統read/write函式
6.5.4 大檔案處理
6.5.5 動態連結程式庫與共用記憶體
6.5.6 動手操作一下mmap
6.6 電腦系統中各個部分的延遲有多少
6.6.1 以時間為度量來換算
6.6.2 以距離為度量來換算
6.7 總結


作者介紹


作者簡介

陸小風(@碼農的荒島求生)

  碩士畢業於北京航空航天大學計算機學院,先後就職於VMware和京東,具有多年軟件系統研發經驗,擅長用通俗易懂的語言講解計算機技術。






相關書籍

開發者傳授PyTorch秘笈

台積電為何這麼強:半導體的計算光刻及佈局優化

最佳能效晶片平台:ARM64架構師高度之程式開發

輕鬆學會iPhone APP實作開發:精心設計17個Lab讓你輕鬆上手