CSAPP 讀書筆記 (1)

寫在前面的話:雖然不想說,但是新的一年又開始了,整理了硬盤里的書,發(fā)現(xiàn)自己真的是光顧著收集書而從來不看,這簡直沒有意義啊,浪費在找書上的時間并沒有得到回報。所以,先從CSAPP這本書開始吧,剛好自己電腦內(nèi)有個 ubuntu,那么就開始吧。


第1章 計算機系統(tǒng)漫游

1.4 處理器讀并解釋存儲在存儲器內(nèi)的指令

shell 是一個命令行解釋器,它輸出一個提示符,等待你輸入一個命令行,然后執(zhí)行這個命令。如果該命令行的第一個單詞不是一個內(nèi)置的 shell 命令,那么 shell 就會假設(shè)這是一個可執(zhí)行文件的名字,它將加載并運行這個文件。

關(guān)于 shell 的定義,簡單明了的解釋。

1.4.1 系統(tǒng)的硬件組成
3.內(nèi)存

主存是一個臨時存儲設(shè)備,在處理執(zhí)行程序時,用來存放程序和程序處理的數(shù)據(jù)。從物理上來說,主存是由一組動態(tài)隨機存取存儲器(DRAM)芯片組成的,從邏輯上來說,存儲器是一個線性的字節(jié)數(shù)組,每個字節(jié)都有其唯一的地址(即數(shù)組索引),這些地址是從零開始的。
一般來說,組成程序的每條機器指令都由不同數(shù)量的字節(jié)構(gòu)成。與C程序變量相對應(yīng)的數(shù)據(jù)項的大小是根據(jù)類型變化的。

有關(guān)內(nèi)存的定義

4.處理器

處理器的核心是一個字長的存儲設(shè)備(或寄存器),成為程序計數(shù)器(PC)。在任何時刻,PC 都指向主存中的某條機器語言指令(即含有該條指令的地址)。

從系統(tǒng)通電開始,直到系統(tǒng)斷電,處理器一直在不斷執(zhí)行程序計數(shù)器指向的指令,再更新程序計數(shù)器,使其指向下一條指令。處理器看上去是按照一個非常簡單的指令執(zhí)行模型來操作的,這個模型是由指令集結(jié)構(gòu)來決定的。在這個模型中,指令按照嚴格的順序執(zhí)行,而執(zhí)行一條指令包含執(zhí)行指定的步驟。處理器從程序計數(shù)器(PC)指向的存儲器處讀取指令,解釋指令中的位,執(zhí)行該指令指示的簡單操作,然后更新PC,使其指向下一條指令,而這條指令并不一定與存儲器中剛剛執(zhí)行的指令相鄰。

這樣的簡單操作并不多,而且操作是圍繞著主存、寄存器文件(register file)算術(shù)/邏輯單元(ALU)進行的。寄存器文件是一個小的存儲設(shè)備,有一些1字長的寄存器組成,每個寄存器都有唯一的名字。ALU計算新的數(shù)據(jù)和地址值。

處理器看上去只是它的指令集結(jié)構(gòu)的簡單實現(xiàn),但是實際上現(xiàn)代處理器使用了非常復(fù)雜的機制來加速程序的執(zhí)行。因此,我們可以這樣區(qū)分處理器的指令集結(jié)構(gòu)和微體系結(jié)構(gòu):指令集結(jié)構(gòu)描述的是每條機器代碼指令的效果;而微體系結(jié)構(gòu)描述的是處理器實際上是如何實現(xiàn)的。

原來CPU是這么工作的啊……CPU通過寄存器得到主存中的機器指令并執(zhí)行(按圖索驥么這是),這些概念應(yīng)該在隨后還會講到,這里的簡單介紹還比較好理解。

1.6 存儲設(shè)備形成層次結(jié)構(gòu)

存儲器層次結(jié)構(gòu)的主要思想是一層上的存儲器作為第一層存儲器的高速緩存。因此寄存器文件就是L1的高速緩存,L1是L2的高速緩存,L2是L3的高速緩存,L3是主存的高速緩存,而主存又是硬盤的高速緩存。

一個存儲器層次結(jié)構(gòu)的示例

1.7 操作系統(tǒng)管理硬件

我們可以把操作系統(tǒng)看成是應(yīng)用程序和硬件之間插入的一層軟件,所有應(yīng)用程序?qū)τ布牟僮鲊L試都必須通過操作系統(tǒng)。

操作系統(tǒng)有兩個基本功能:1)防止硬件被失控的應(yīng)用程序濫用。2)向應(yīng)用程序提供簡單一致的機制來控制復(fù)雜而又通常大相徑庭的低級硬件設(shè)備。操作系統(tǒng)通過幾個基本的抽象概念(進程、虛擬存儲器和文件)來實現(xiàn)這兩個功能。如圖1-11,文件是對 I/O 設(shè)備的抽象表示,虛擬存儲器是對主存和硬盤 I/O 設(shè)備的抽象表示,進程則是對處理器、主存、和 I/O 設(shè)備的抽象表示。

第10頁例圖

操作系統(tǒng)的作用,想起上操作系統(tǒng)課程的時候老師將硬盤時強調(diào)的物理地址和邏輯地址。操作系統(tǒng)應(yīng)該可以看成是一個超大的底層的應(yīng)用程序吧?其他所有應(yīng)用程序都要運行在操作系統(tǒng)之上。

1.7.1 進程

進程是操作系統(tǒng)對一個正在運行的程序的一種抽象。在一個系統(tǒng)上可以同時運行多個進程,而每個進程都好像獨占地使用硬件。而并發(fā)運行,則是說一個進程的指令和另一個進程的指令是交錯執(zhí)行的。傳統(tǒng)系統(tǒng)在一個時刻只能執(zhí)行一個程序,而先進的多核處理器同時能夠執(zhí)行多個程序。無論是在單核還是多核系統(tǒng)中,一個 CPU 看上去都像是在并發(fā)地執(zhí)行多個進程,這是通過處理器在進程間切換來實現(xiàn)的。操作系統(tǒng)實現(xiàn)這種交錯執(zhí)行的機制稱為上下文切換( context switch )

操作系統(tǒng)保持跟蹤進程運行所需的所有狀態(tài)信息,這種狀態(tài),也就是context,它包括許多信息,例如 PC 和寄存器文件的當前值,以及主存的內(nèi)容。在任何一個時刻,單處理器系統(tǒng)都只能執(zhí)行一個進程的代碼。當操作系統(tǒng)決定要把控制權(quán)從當前進程轉(zhuǎn)移到某個新進程時,就會進行**context switch **,即保存當前進程的 context、恢復(fù)新進程的 context,然后將控制權(quán)傳遞到新進程,新進程就會從上次停止的地方開始。

示例場景中有兩個并發(fā)的進程:shell 進程和 hello 進程。起初,只有 shell 進程在運行,即等待命令行上的輸入。當我們讓它運行 hello 程序時,shell 通過調(diào)用一個專門的函數(shù),即系統(tǒng)調(diào)用,來執(zhí)行我們的請求,系統(tǒng)調(diào)用會將控制權(quán)交給操作系統(tǒng)。操作系統(tǒng)保存 shell 進程的 context,創(chuàng)建一個新的 hello 進程及 context,然后將控制權(quán)傳遞給新的 hello 進程,hello 進程終止后,操作系統(tǒng)恢復(fù) shell 進程的 context,并將控制權(quán)傳回給它,shell 進程將繼續(xù)等待下一個命令行輸入。

根據(jù)書中給的例子,基本能看懂 context switch 在例子中是怎樣一回事了,話說回來看這本書真的好像在看操作系統(tǒng)啊。

1.7.2 線程

在現(xiàn)代系統(tǒng)中,一個進程實際上可以由多個成為線程的執(zhí)行單元組成,每個線程都運行在進程的 context 中,并共享同樣的代碼和全局數(shù)據(jù)。

1.7.3 虛擬存儲器

虛擬存儲器是一個抽象概念,它為每個進程提供了一個假象,即每個進程都在獨占地使用主存,每個進程看到的是一致的存儲器,成為虛擬地址空間。下圖所示的是 Linux 進程的虛擬地址空間(其他 Unix 系統(tǒng)的設(shè)計也與此類似)。在 Linux中,地址空間的底部區(qū)域存放用戶進程定義的代碼和數(shù)據(jù)。下圖所示的地址是從下往上增大的。

12頁例圖

每個進程看到的虛擬地址空間由大量準確定義的區(qū)構(gòu)成,每個區(qū)都有專門的功能。我們從最低的地址開始,逐步向上介紹

  • 程序代碼和數(shù)據(jù)。對于所有的進程來說,代碼是從同一固定地址開始,緊接著的是和 C 全局變量相對應(yīng)的數(shù)據(jù)位置。代碼和數(shù)據(jù)區(qū)是直接按照可執(zhí)行目標文件的內(nèi)容初始化的。在示例中就是可執(zhí)行文件 hello。
    (PS:hello 是通過鏈接器在鏈接階段獲得的,可被加載到內(nèi)存中)
  • 堆。代碼和數(shù)據(jù)后緊隨的是運行時堆。代碼和數(shù)據(jù)區(qū)是在進程一開始運行時就被規(guī)定了大小,于此不同,當調(diào)用如 mallocfree 這樣的 C 標準庫函數(shù)時,堆可以在運行時動態(tài)地拓展和收縮。
  • 共享庫。大約在地址空間的中間部分是一塊 用來存放像 C 標準庫和教學(xué)庫這樣共享庫和代碼的數(shù)據(jù)。
  • 棧。位于用戶虛擬地址空間頂部的是用戶棧,編譯器用它來實現(xiàn)函數(shù)調(diào)用,和堆一樣,用戶棧在程序執(zhí)行期間可以動態(tài)地拓展和收縮。特別是每次我們調(diào)用一個函數(shù)時,棧就會增長,從一個函數(shù)返回時,棧就會收縮。
  • 內(nèi)核虛擬存儲器。內(nèi)核總是駐留在內(nèi)存中,是操作系統(tǒng)的一部分。地址空間頂部的區(qū)域是為內(nèi)核保留的,不允許應(yīng)用程序讀寫這個區(qū)域的內(nèi)容或者直接調(diào)用內(nèi)核代碼定義的函數(shù)。
1.7.4 文件

文件就是字節(jié)序列。每個 I/O 設(shè)備,包括磁盤、鍵盤、顯示器,甚至網(wǎng)絡(luò),都可以視為文件。系統(tǒng)中的所有輸入輸出都是通過一小組稱為 Unix I/O 的系統(tǒng)函數(shù)調(diào)用讀寫文件來實現(xiàn)的。
文件向應(yīng)用程序提供了一個統(tǒng)一的視角,來看待系統(tǒng)中可能含有的所有各式各樣的 I/O 設(shè)備。進一步說,同一個程序可以在使用不同磁盤技術(shù)的不同系統(tǒng)上運行。

這說的是硬件無關(guān)性么?

1.9 重要主題

1.9.1 并發(fā)和并行

并發(fā)(concurrency) 是一個通用的概念,指一個同事具有多個活動的系統(tǒng);而術(shù)語并行(parallelism)指的是用并發(fā)使一個系統(tǒng)運行得更快。

1.9.2 計算機系統(tǒng)中抽象的重要性

在處理器里,指令集結(jié)構(gòu)提供了對實際處理器硬件的抽象。使用這個抽象,機器代碼程序代碼程序表現(xiàn)得好像它是運行在一個一次只執(zhí)行一條指令的處理器上。底層的硬件比抽象描述的要復(fù)雜精細的多,它并行地執(zhí)行多條指令,但又總是與那個簡單有序的模型保持一致。只要執(zhí)行模型一樣,不同的處理器實現(xiàn)也能執(zhí)行同樣的機器代碼,而又提供不同的開銷和性能。

17頁例圖

在學(xué)習(xí)操作系統(tǒng)時,我們介紹了三個抽象,文件是對 I/O 的抽象,虛擬存儲器是對程序存儲器的抽象,而進程是對一個正在運行的程序的抽象。而虛擬機提供對整個計算機(包括操作系統(tǒng)、處理器和程序)的抽象。

1.10 小結(jié)

  • 因為計算機把大量的時間用于存儲器、I/O 設(shè)備和 CPU 寄存器之前復(fù)制數(shù)據(jù),所以將系統(tǒng)中的存儲設(shè)備劃分為層次結(jié)構(gòu)。
  • 在層次結(jié)構(gòu)中,高層的存儲設(shè)備比底層的存儲設(shè)備要快,單位比特開銷也更高。較高層次存儲設(shè)備可以作為較低層次設(shè)備的高速緩存。通過理解和運用這種存儲層次結(jié)構(gòu)的知識,程序員可以優(yōu)化 C 程序的性能。
  • 從特殊角度來看,網(wǎng)絡(luò)就是一種 I/O 設(shè)備。

PS : 書中的1.9節(jié)中,關(guān)于并行和并發(fā)的三個層次(15-17頁)可以說完全沒看懂……應(yīng)該在隨后的章節(jié)中還會進一步解釋吧。先記錄下。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,881評論 18 139
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關(guān)于...
    SeanCST閱讀 7,867評論 0 27
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,116評論 25 708
  • 1.原來有些樹不是不會開花,只是不適合,或者錯過了開花的年齡。 2.歲月褪去了灰白,我發(fā)現(xiàn)我的天空依舊像童話般蔚藍...
    Alones閱讀 512評論 5 5
  • “天那!少谷主居然帶回來了這么個絕色美女啊!” “是啊~這也太美了吧,少谷主果然好本事。” “不如.....咱們先...
    隼舞閱讀 298評論 0 0