本章通過跟蹤hello程序的生命周期來開始對計算機系統進行學習。一個源程序從它被程序員創建開始,到在系統上運行,輸出簡單的消息,然后終止。我們將沿著這個程序的生命周期,簡要地介紹一些逐步出現的關鍵概念、專業術語和組成部分。
@[TOC]
??好久沒有更新博客了,從國慶節到現在一直在整理秋招的一些資料,簡歷模版,嵌入式軟件面試知識點總結,秋招筆試題目整理,面經總結復盤等。一共整理了將近400頁,16W字。順便把百度網盤的資料也整理了下,到10.16才整理完(需要資料的在主頁有我聯系方式)。不得不說,整理資料是真的磨人性。
??接下來的計劃是補充下操作系統和計算機組成原理相關的知識。從《深入理解計算機系統》這本書開始吧,系統學習下《深入理解計算機系統》這本書,還有9個Lab可以做下,以便加深理解。初步計劃一周一章(不知道行不行),爭取在放寒假前做完這些。
??我會把看書過程中一些重要的知識點,概念的理解以及做實驗的詳細過程都放在博客深入理解計算機系統專欄中。歡迎關注我的博客以便第一時間獲取文章更新的內容。
??下面就是本書第一章的一個簡單總結。
源程序是如何存儲的
#include <stdio.h>
int main()
{
printf("hello,world\n");
return 0;
}
??以上程序是我們通過文本編輯器創建的文本文件,保存為hello.c。源程序實際上就是一個由值0和1組成的位(又稱為比特)序列,8個位被組織成一組,稱為字節。每個字節表示程序中的某些文本字符。現代計算機都使用ASCII標準來表示文本字符。hello.c程序的ASCII文本字符如下所示。
??hello.c程序是以字節序列的方式儲存在文件中的。
??hello.c的表示方法說明了一個基本思想:系統中所有的信息——包括磁盤文件、內存中的程序、內存中存放的用戶數據以及網絡上傳送的數據,都是由一串比特表示的。區分不同數據對象的唯一方法是我們讀到這些數據對象的上下文。
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/qq_16933601/article/details/109169750
源程序到可執行文件的過程
??GCC編譯器驅動程序讀取源程序文件hello.c,并把它翻譯成一個可執行目標文件hello。這個翻譯過程可分為四個階段:預編譯,編譯,匯編,鏈接。
預編譯
??在預編譯的過程中,主要處理源代碼中的預處理指令,引入頭文件,去除注釋,處理所有的條件編譯指令(#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程序需要把用戶輸入的內容作為一個變量使用,而這個變量一定在內存中有個地址,所以它最終會到達內存。
??當我們在鍵盤上敲回車鍵時, shell程序就知道我們已經結東了命令的輸入。然后shell執行一系列指令來加載可執行的hello文件,這些指令將hello目標文件中的代碼和數據從磁盤復制到主存。數據包括最終會被輸出的字符串“ hello,wor1d\n”。信息流向如下所示。
??磁盤->磁盤控制器->I/O總線->I/O橋->內存總線->主存
??這種訪問數據的方式數據不會經過CPU,而是直接從磁盤到主存,這種方式稱為DMA。DMA(直接存儲器訪問)有利于減輕CPU的負荷,使CPU可以在數據轉移的同時做其它任務。
??加載完hello文件后,CPU將會開始從hello程序的主函數處執行指令。這些指令將“hello,world\n”字符串中的字節從主存復制到寄存器文件,再從寄存器文件中復制到顯示設備,最終顯示在屏幕上。信息流向如下圖所示。
??主存->寄存器->系統總線->I/O橋->I/O總線->圖形適配器->顯示器
高速緩存
??通過運行hello程序,我們可以知道,指令和數據需要多次在寄存器、主存、磁盤之間來回復制,這些復制其實就是開銷,減慢了程序工作的速度。這個時候我們就需要高速緩存存儲器(cache memory)來解決這個問題。
??L1高速緩存的容量可以達到數萬字節,訪問速度幾乎和訪問寄存器文件一樣快。
??L2高速緩存容量為數十萬到數百萬字節,通過一條特殊的總線連接到處理器。進程訪問L2高速緩存的時間要比訪問L1高速緩存的時間長5倍,但是這仍然比訪問主存的時間快5~10倍。
??L1和L2高速緩存是用一種叫做 靜態隨機訪問存儲器(SRAM) 的硬件技術實現的。
??高速緩存局部性原理:程序具有訪問局部區域中的數據和代碼的趨勢。因此,高速緩存存儲器作為暫時的集結區域,存放處理器近期可能會需要的信息。
存儲設備的層次結構
??從上至下,設備的訪問速度越來越慢、容量越來越大,并且每字節的造價也越來越便宜。寄存器文件在層次結構中位于最頂部,也就是第0級或記為L0。
<img src="https://gitee.com/dongxingbo/Picture/raw/master//%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F/%E5%9B%BE1-9_%E5%AD%98%E5%82%A8%E5%99%A8%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84%E5%9B%BE.png" alt="image-20201019200335061" style="zoom: 80%;" />
??存儲器層次結構的主要思想是上一層的存儲器作為低一層存儲器的高速緩存。因此,寄存器文件就是L1的高速緩存,L1是L2的高速緩存,L2是L3的高速緩存,L3是主存的高速緩存,而主存又是磁盤的高速緩存。
操作系統管理硬件
??操作系統是應用程序和硬件之間插入的一層軟件。所有應用程序對硬件的操作嘗試都必須通過操作系統。
??操作系統有兩個基本功能:(1)防止硬件被失控的應用程序濫用;(2)向應用程序提供簡單一致的機制來控制復雜而又通常大不相同的低級硬件設備。
??操作系統通過幾個基本的抽象概念(進程、虛擬內存和文件)來實現這兩個功能:文件是對I/O設備的抽象表示,虛擬內存是對主存和磁盤I/O設備的抽象表示,進程則是對處理器、主存和I/O設備的抽象表示。
進程&線程
??進程是操作系統對一個正在運行的程序的一種抽象。在一個系統上可以同時運行多個進程,而每個進程都好像在獨占地使用硬件。而并發運行,則是說一個進程的指令和另個進程的指令是交錯執行的。
??上下文:操作系統保持和跟蹤進程運行所需的所有狀態信息(PC值,主存的內容等)。
??上下文切換:操作系統通過控制處理器在進程間切換以達到交錯執行的目的。
??從一個進程到另一個進程的轉換是由操作系統內核( kernel)管理的。內核是操作系統代碼常駐主存的部分。內核不是一個獨立的進程。相反,它是系統管理全部進程所用代碼和數據結構的集合。
<img src="https://gitee.com/dongxingbo/Picture/raw/master//%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F/%E5%9B%BE1-12_%E8%BF%9B%E7%A8%8B%E7%9A%84%E4%B8%8A%E4%B8%8B%E6%96%87%E5%88%87%E6%8D%A2.png" alt="image-20201019203213287" style="zoom: 80%;" />
一個進程由多個稱為線程的執行單元組成,每個線程都運行在進程的上下文中,并共享同樣的代碼和全局數據。多線程比多進程更容易共享數據,而且線程間切換所有的開銷要遠小于進程切換。
虛擬內存
??虛擬內存是一個抽象概念,它為每個進程提供了一個假象,即每個進程都在獨占地使用主存。每個進程看到的內存都是一致的,稱為虛擬地址空間。
<img src="https://gitee.com/dongxingbo/Picture/raw/master//%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F/%E5%9B%BE1-13_%E8%BF%9B%E7%A8%8B%E7%9A%84%E8%99%9A%E6%8B%9F%E5%9C%B0%E5%9D%80%E7%A9%BA%E9%97%B4.png" alt="image-20201019203450101" style="zoom: 80%;" />
??上圖將虛擬地址空間分為了若干個部分,并用箭頭表示該部分的擴展方向。最下端地址為0,向上地址逐漸增長。每個部分作用如下:
?? 程序代碼和數據: 存放可執行程序代碼和代碼中的全局變量。
??堆: 用于動態申請的內存變量,比如malloc
函數申請的動態內存空間,可以向上擴展。
??共享庫: 用于存放C語言庫函數的代碼和數據。本例中即printf
的代碼和數據。
??棧: 位于虛擬地址空間的頂部,用于函數調用、存放局部變量等。當我們調用一個函數時,棧會向下擴展,返回時,向上收縮。
??內核虛擬內存: 地址空間頂部的區域是為內核保留的。不允許應用程序讀寫這個區域的內容或者直接調用內核代碼定義的函數。相反,它們必須調用內核來執行這些操作。對于一個64為的操作系統來說,用戶空間為0-3G,內核空間為3G-4G。(用戶空間和內核空間有何區別,見秋招資料整理中的嵌入式軟件工程師筆試面試知識點總結)
并發&并行
??并行:指在同一時刻,有多條指令在多個處理器上同時執行。所以無論從微觀還是從宏觀來看,二者都是一起執行的。
[圖片上傳失敗...(image-3ecc10-1612606053156)]
??并發:指在同一時刻只能有一條指令執行,但多個進程指令被快速的輪換執行,使得在宏觀上具有多個進程同時執行的效果,但在微觀上并不是同時執行的,只是把時間分成若干段,使多個進程快速交替的執行。
[圖片上傳失敗...(image-867bb-1612606053156)]
多核處理器&多線程
??多核處理器:多核處理器是將多個CPU(稱為“核”)集成到一個集成電路芯片上。如下圖所示,微處理器芯片有4個CPU核,每個核都有自己的L1和L2高速緩存,其中的L1高速緩存分為兩個部分——一個保存最近取到的指令,另一個存放數據。這些核共享更高層次的高速緩存,以及到主存的接口。
<img src="https://gitee.com/dongxingbo/Picture/raw/master//%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F/%E5%9B%BE1-17_%E5%A4%9A%E6%A0%B8%E5%A4%84%E7%90%86%E5%99%A8%E4%BA%8C%E7%AD%89%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84.png" alt="image-20201019212750093" />
??超線程:超線程,有時稱為同時多線程( simultaneous multi-threading),是一項允許一個CPU執行多個控制流的技術。舉個例子,Intel Core i7處理器可以讓每個核執行兩個線程,所以一個4核的系統實際上可以并行地執行8個線程。
??養成習慣,先贊后看!如果覺得寫的不錯,歡迎一鍵三連,謝謝!
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/qq_16933601/article/details/109169750