《深刻理解計算機系統》(CSAPP)讀書筆記 —— 第一章 計算機系統漫遊

本章經過跟蹤hello程序的生命週期來開始對計算機系統進行學習。一個源程序從它被程序員建立開始,到在系統上運行,輸出簡單的消息,而後終止。咱們將沿着這個程序的生命週期,簡要地介紹一些逐步出現的關鍵概念、專業術語和組成部分。程序員

@面試

  很久沒有更新博客了,從國慶節到如今一直在整理秋招的一些資料,簡歷模版,嵌入式軟件面試知識點總結,秋招筆試題目整理,面經總結覆盤等。一共整理了將近400頁,16W字。順便把百度網盤的資料也整理了下,到10.16才整理完(須要資料的在主頁有我聯繫方式)。不得不說,整理資料是真的磨人性。shell

  接下來的計劃是補充下操做系統和計算機組成原理相關的知識。從《深刻理解計算機系統》這本書開始吧,系統學習下《深刻理解計算機系統》這本書,還有9個Lab能夠作下,以便加深理解。初步計劃一週一章(不知道行不行),爭取在放寒假前作完這些。編程

  我會把看書過程當中一些重要的知識點,概念的理解以及作實驗的詳細過程都放在博客深刻理解計算機系統專欄中。歡迎關注個人博客以便第一時間獲取文章更新的內容。數組

  下面就是本書第一章的一個簡單總結。緩存

源程序是如何存儲的

#include <stdio.h>
int main()
{
	printf("hello,world\n");
	return 0;
}

  以上程序是咱們經過文本編輯器建立的文本文件,保存爲hello.c。源程序實際上就是一個由值0和1組成的位(又稱爲比特)序列,8個位被組織成一組,稱爲字節。每一個字節表示程序中的某些文本字符。現代計算機都使用ASCII標準來表示文本字符。hello.c程序的ASCII文本字符以下所示。網絡

image-20201019170810469

  hello.c程序是以字節序列的方式儲存在文件中的。數據結構

  hello.c的表示方法說明了一個基本思想:系統中全部的信息——包括磁盤文件、內存中的程序、內存中存放的用戶數據以及網絡上傳送的數據,都是由一串比特表示的。區分不一樣數據對象的惟一方法是咱們讀到這些數據對象的上下文多線程

源程序到可執行文件的過程

  GCC編譯器驅動程序讀取源程序文件hello.c,並把它翻譯成一個可執行目標文件hello。這個翻譯過程可分爲四個階段:預編譯,編譯,彙編,連接。併發

image-20201019171458969

預編譯

  在預編譯的過程當中,主要處理源代碼中的預處理指令,引入頭文件,去除註釋,處理全部的條件編譯指令(#ifdef,#ifndef,#else,#elif,#endif),宏的替換,添加行號,保留全部的編譯器指令

編譯

  在預處理結束後,進行的是編譯。編譯過程所進行的是對預處理後的文件進行語法分析,詞法分析,語義分析,符號彙總,而後生成彙編代碼

彙編

  彙編過程將彙編代碼轉成二進制文件,二進制文件就可讓機器來讀取。每一條彙編語句都會產生一句機器語言。

連接

  由彙編程序生成的目標文件並不能當即就被執行,其中可能還有許多沒有解決的問題。例如,某個源文件中的函數可能引用了另外一個源文件中定義的某個符號(如變量或者函數調用等);在程序中可能調用了某個庫文件中的函數等等。全部這些問題,都須要經連接程序的處理方能得以解決連接程序的主要工做就是將有關的目標文件彼此相鏈接,也即將在一個文件中引用的符號同該符號在另一個文件中的定義鏈接起來,使得全部的這些目標文件成爲一個可以被操做系統裝入執行的統一總體

shell是什麼

  shell是一個命令行解釋器,它輸出一個提示符,等待輸入一個命令行,而後執行這個命令。若是該命令行的第一個單詞不是一個內置的shell命令,那麼 shell就會假設這是個可執行文件的名字,它將加載並運行這個文件。

典型系統的硬件組成

總線

  貫穿整個系統的是一組電子通道,稱做總線。一般總線中傳輸的是固定長度的字節塊,也就是字(word)。字中的字節數(字長)是一個基本的系統參數。不一樣系統字長不一樣。好比32位系統的字長爲4個字節,64位系統的字長爲8個字節。

IO設備

  I/O(輸入/輸出)設備是系統與外部世界的聯繫通道。咱們的示例系統包括四個I/O設備:做爲用戶輸入的鍵盤和鼠標,做爲用戶輸出的顯示器,以及用於長期存儲數據和程序的磁盤驅動器(簡單地說就是磁盤)。

  每一個IO設備都經過一個控制器或適配器與I/O總線相連。控制器和適配器之間的區別主要在於它們的封裝方式。控制器是I/O設備自己或者系統的主印製電路板(一般稱做主板)上的芯片組。而適配器則是一塊插在主板插槽上的卡。不管如何,它們的功能都是在I/O總線和I/O設備之間傳遞信息

主存

  主存是一個臨時存儲設備,在處理器執行程序時,用來存放程序和程序處理的數據。從物理上來講,主存是由一組動態隨機存取存儲器(DRAM)芯片組成的。從邏輯上來講,存儲器是一個線性的字節數組,每一個字節都有其惟一的地址(數組索引),這些地址是從零開始的。

處理器

  中央處理單元(CPU),簡稱處理器,是執行存儲在主存中指令的引擎。處理器的核心是一個大小爲一個字的存儲設備(或寄存器),稱爲程序計數器(PC)。在任什麼時候刻,PC都指向主存中的某條機器語言指令(即含有該條指令的地址)。

運行hello程序

  shell讀取到咱們從鍵盤輸入的「./hello」後,計算機中的信息流向以下圖紅線所示:

  鍵盤->USB控制器->I/O總線->I/O橋->系統總線->寄存器

  寄存器->系統總線->I/O橋->內存總線->主存

  shell程序須要把用戶輸入的內容做爲一個變量使用,而這個變量必定在內存中有個地址,因此它最終會到達內存。

image-20201019191356753

  當咱們在鍵盤上敲回車鍵時, shell程序就知道咱們已經結東了命令的輸入。而後shell執行一系列指令來加載可執行的hello文件,這些指令將hello目標文件中的代碼和數據從磁盤複製到主存。數據包括最終會被輸出的字符串「 hello,wor1d\n」。信息流向以下所示。

  磁盤->磁盤控制器->I/O總線->I/O橋->內存總線->主存

  這種訪問數據的方式數據不會通過CPU,而是直接從磁盤到主存,這種方式稱爲DMA。DMA(直接存儲器訪問)有利於減輕CPU的負荷,使CPU能夠在數據轉移的同時作其它任務。

image-20201019191522808

  加載完hello文件後,CPU將會開始從hello程序的主函數處執行指令。這些指令將「hello,world\n」字符串中的字節從主存複製到寄存器文件,再從寄存器文件中複製到顯示設備,最終顯示在屏幕上。信息流向以下圖所示。

  主存->寄存器->系統總線->I/O橋->I/O總線->圖形適配器->顯示器

image-20201019191644207

高速緩存

  經過運行hello程序,咱們能夠知道,指令和數據須要屢次在寄存器、主存、磁盤之間來回複製,這些複製其實就是開銷,減慢了程序工做的速度。這個時候咱們就須要高速緩存存儲器(cache memory)來解決這個問題。

image-20201019195237101

  L1高速緩存的容量能夠達到數萬字節,訪問速度幾乎和訪問寄存器文件同樣快。

  L2高速緩存容量爲數十萬到數百萬字節,經過一條特殊的總線鏈接處處理器。進程訪問L2高速緩存的時間要比訪問L1高速緩存的時間長5倍,可是這仍然比訪問主存的時間快5~10倍。

  L1和L2高速緩存是用一種叫作 靜態隨機訪問存儲器(SRAM) 的硬件技術實現的。

  高速緩存局部性原理:程序具備訪問局部區域中的數據和代碼的趨勢。所以,高速緩存存儲器做爲暫時的集結區域,存放處理器近期可能會須要的信息

存儲設備的層次結構

  從上至下,設備的訪問速度愈來愈慢、容量愈來愈大,而且每字節的造價也愈來愈便宜。寄存器文件在層次結構中位於最頂部,也就是第0級或記爲L0。

image-20201019200335061

  存儲器層次結構的主要思想是上一層的存儲器做爲低一層存儲器的高速緩存。所以,寄存器文件就是L1的高速緩存,L1是L2的高速緩存,L2是L3的高速緩存,L3是主存的高速緩存,而主存又是磁盤的高速緩存。

操做系統管理硬件

  操做系統是應用程序和硬件之間插入的一層軟件。全部應用程序對硬件的操做嘗試都必須經過操做系統。

  操做系統有兩個基本功能:(1)防止硬件被失控的應用程序濫用;(2)嚮應用程序提供簡單一致的機制來控制複雜而又一般大不相同的低級硬件設備。

  操做系統經過幾個基本的抽象概念(進程、虛擬內存和文件)來實現這兩個功能:文件是對I/O設備的抽象表示,虛擬內存是對主存和磁盤I/O設備的抽象表示,進程則是對處理器、主存和I/O設備的抽象表示

image-20201019201009252

進程&線程

  進程是操做系統對一個正在運行的程序的一種抽象。在一個系統上能夠同時運行多個進程,而每一個進程都好像在獨佔地使用硬件。而併發運行,則是說一個進程的指令和另個進程的指令是交錯執行的。

  上下文:操做系統保持和跟蹤進程運行所需的全部狀態信息(PC值,主存的內容等)。

  上下文切換:操做系統經過控制處理器在進程間切換以達到交錯執行的目的。

  從一個進程到另外一個進程的轉換是由操做系統內核( kernel)管理的。內核是操做系統代碼常駐主存的部分。內核不是一個獨立的進程。相反,它是系統管理所有進程所用代碼和數據結構的集合

image-20201019203213287

一個進程由多個稱爲線程的執行單元組成,每一個線程都運行在進程的上下文中,並共享一樣的代碼和全局數據。多線程比多進程更容易共享數據,並且線程間切換全部的開銷要遠小於進程切換。

虛擬內存

  虛擬內存是一個抽象概念,它爲每一個進程提供了一個假象,即每一個進程都在獨佔地使用主存。每一個進程看到的內存都是一致的,稱爲虛擬地址空間。

image-20201019203450101

  上圖將虛擬地址空間分爲了若干個部分,並用箭頭表示該部分的擴展方向。最下端地址爲0,向上地址逐漸增加。每一個部分做用以下:

   程序代碼和數據: 存放可執行程序代碼和代碼中的全局變量。

  堆: 用於動態申請的內存變量,好比malloc函數申請的動態內存空間,能夠向上擴展。

  共享庫: 用於存放C語言庫函數的代碼和數據。本例中即printf的代碼和數據。

  棧: 位於虛擬地址空間的頂部,用於函數調用、存放局部變量等。當咱們調用一個函數時,棧會向下擴展,返回時,向上收縮。

  內核虛擬內存: 地址空間頂部的區域是爲內核保留的。不容許應用程序讀寫這個區域的內容或者直接調用內核代碼定義的函數。相反,它們必須調用內核來執行這些操做。對於一個64爲的操做系統來講,用戶空間爲0-3G,內核空間爲3G-4G。(用戶空間和內核空間有何區別,見秋招資料整理中的嵌入式軟件工程師筆試面試知識點總結)

併發&並行

  並行:指在同一時刻,有多條指令在多個處理器上同時執行。因此不管從微觀仍是從宏觀來看,兩者都是一塊兒執行的。

img

  併發:指在同一時刻只能有一條指令執行,但多個進程指令被快速的輪換執行,使得在宏觀上具備多個進程同時執行的效果,但在微觀上並非同時執行的,只是把時間分紅若干段,使多個進程快速交替的執行

img

多核處理器&多線程

  多核處理器:多核處理器是將多個CPU(稱爲「核」)集成到一個集成電路芯片上。以下圖所示,微處理器芯片有4個CPU核,每一個核都有本身的L1和L2高速緩存,其中的L1高速緩存分爲兩個部分——一個保存最近取到的指令,另外一個存放數據。這些核共享更高層次的高速緩存,以及到主存的接口。

image-20201019212750093

  超線程:超線程,有時稱爲同時多線程( simultaneous multi-threading),是一項容許一個CPU執行多個控制流的技術。舉個例子,Intel Core i7處理器可讓每一個核執行兩個線程,因此一個4核的系統實際上能夠並行地執行8個線程。

  養成習慣,先贊後看!若是以爲寫的不錯,歡迎一鍵三連,謝謝!

CSDN:點擊訪問個人CSDN博客
歡迎歡迎關注個人公衆號:嵌入式與Linux那些事,領取秋招筆試面試大禮包(華爲小米等大廠面經,嵌入式知識點總結,筆試題目,簡歷模版等)和2000G學習資料。

相關文章
相關標籤/搜索