【深入理解计算机系统 01】计算机系统漫游
01計算機系統(tǒng)漫游
本書的主要作用:幫助我們了解當(dāng)我們在系統(tǒng)上執(zhí)行hello程序時,系統(tǒng)發(fā)生了什么以及為什么會這樣
#include <stdio.h>int main() {printf("hello, world\n");return 0; }信息是「位+上下文」
hello的生命周期從最初的源程序(源文件) 開始,是一個名為hello.c的文本文件
-
源程序?qū)嶋H上就是一個由值0和1組成的位(也稱為比特)序列
-
8個位被組織為一組,稱為字節(jié) ,每個字節(jié)表示程序中的某些文本字符
-
例如,ASCII標(biāo)準(zhǔn)使用一個唯一的單字節(jié)大小的整數(shù)值表示每個字符
hello.c以字節(jié)序列的方式存儲在文件當(dāng)中,每一個字節(jié)都具有一個整數(shù)值
-
例如,# 對應(yīng)的整數(shù)為35,即0010 0011
-
例如,i對應(yīng)的整數(shù)為105,即0110 1001
-
例如,\n對應(yīng)的整數(shù)為110,每一行結(jié)尾都具有一個以表示換行
-
例如,SP對應(yīng)的整數(shù)為32,有空格的地方就具有它
計算機系統(tǒng)中的所有信息,都是由一串比特表示的,并通過上下文進行區(qū)分
-
一個同樣的字節(jié)序列,可能表示一個整數(shù)、浮點數(shù)、字符串或者機器指令
-
數(shù)字的機器表示方式與實際的整數(shù)和實數(shù)不同,它們是對真值的有限近似
程序被其他程序翻譯成不同的格式
hello程序從C語言開始,是適合人類閱讀的方式,但最終要化為一系列低級機器語言指令,
-
這些指令按照一種稱為可執(zhí)行目標(biāo)程序的格式進行打包
-
打包完成以二進制磁盤文件的形式進行存儲,目標(biāo)程序也稱為可執(zhí)行目標(biāo)文件
-
Unix系統(tǒng)上,整個過程的轉(zhuǎn)化由編譯器驅(qū)動程序完成
上述過程對應(yīng)的指令為
gcc -o hello hello.c整個過程中,由GCC完成將源文件hello.c翻譯為可執(zhí)行文件hello
翻譯的過程可以劃分為四個階段,對應(yīng)執(zhí)行的程序如下所示,四者構(gòu)成了編譯系統(tǒng)
-
預(yù)處理器(cpp)
-
根據(jù)以字符#開頭的命令,修改原始程序
-
例如根據(jù)#include <stdio.h>讀取系統(tǒng)頭文件stdio.h的內(nèi)容,并插入程序中
-
最終的結(jié)果以.i作為文件擴展名
-
-
編譯器(ccl)
-
編譯器將文本文件hello.i翻譯為文本文件hello.s,包含一個匯編語言程序
-
該程序包含函數(shù)main的定義,其中的每條語句都以一種文本格式描述了一條低級機器語言指令
-
-
匯編器(as)
-
將hello.s翻譯成機器語言指令,并打包成可重定位目標(biāo)程序 ,保存在hello.o
-
該階段保存的文件是二進制文件,用本文編輯器打開是亂碼
-
-
鏈接器(ld)
-
hello程序調(diào)用了printf函數(shù),是標(biāo)準(zhǔn)C庫中的函數(shù),存在一個名為printf.o的單獨編譯完成的目標(biāo)文件當(dāng)中
-
該文件需要合并到hello.o程序中,合并完成得到hello的可執(zhí)行目標(biāo)文件
-
可執(zhí)行目標(biāo)文件可以被加載到內(nèi)存當(dāng)中,由系統(tǒng)執(zhí)行
-
處理器讀并解釋存儲在內(nèi)存中的指令
hello.c源程序被編譯系統(tǒng)翻譯為可執(zhí)行目標(biāo)文件hello,并存放在磁盤上。
如果是在Unix系統(tǒng)上想要運行這個程序,當(dāng)需要將文件名輸入到shell的應(yīng)用程序當(dāng)中
shell是一個命令行解釋器,輸出一個提示符,等待輸入一個命令行,然后執(zhí)行這個命令,執(zhí)行完畢之后繼續(xù)輸出一個提示符,等待下一個輸入的命令
系統(tǒng)的硬件組成
總線
總線是貫穿整個系統(tǒng)的一組電子管道,攜帶信息字節(jié)并在各個部件之間傳遞
總線被設(shè)計為傳送定長的字節(jié)塊,也就是字(word),64位系統(tǒng)為8個字節(jié),32位系統(tǒng)為4個字節(jié)
I/O設(shè)備
系統(tǒng)與外部世界的聯(lián)系通道
例如鍵盤、鼠標(biāo)、顯示器、磁盤等,通過控制器或適配器與I/O總線相連接。
控制器與適配器的差別在于封裝方式,功能都是在I/O設(shè)備和I/O總線之間傳遞信息
主存
臨時存儲設(shè)備,在處理器執(zhí)行程序的時候,用來存放程序和程序處理的數(shù)據(jù)
邏輯上即為一個線性的字節(jié)數(shù)組,每個字節(jié)都有其唯一的地址(數(shù)組索引),從零開始
處理器
解釋(執(zhí)行)存儲在主存中指令的引擎
核心是一個大小為一個字的寄存器,稱為程序計數(shù)器(PC),在任何時候都指向主存中的某條及其語言指令(即含有該指令的地址)
從系統(tǒng)上電開始,處理器一直在執(zhí)行PC所指向的指令,再更新PC,指向下一條指令
運行hello程序
shell 是什么?shell 是一個命令解釋程序,如果命令行的第一個單詞不是內(nèi)置的 shell 命令,shell 就會對這個文件進行加載并運行。此處,shell 加載并且運行 hello 程序,屏幕上顯示 “Hello World” 內(nèi)容,hello 程序運行結(jié)束并退出,shell 繼續(xù)等待下一個命令的輸入。
在 shell 中輸入./hello之后,會將其逐一讀入寄存器,處理器會將其再放到內(nèi)存當(dāng)中。當(dāng)按下回車之后,shell 程序就知道我們已經(jīng)完成了命令的輸入, 然后執(zhí)行一系列的指令來加載可執(zhí)行文件 hello
這些指令將 hello 目標(biāo)文件中的代碼和數(shù)據(jù)從磁盤復(fù)制到主存,數(shù)據(jù)就是我們要顯示輸出的”Hello World\n” ,這個復(fù)制的過程將利用 DMA(Direct Memory Access) 技術(shù),數(shù)據(jù)可以不經(jīng)過處理器,從磁盤直接到達內(nèi)存。
當(dāng)可執(zhí)行文件 hello 中的代碼和數(shù)據(jù)都加載到主存之后,處理器就開始執(zhí)行 hello 程序的 main 程序中的機器語言指令,這些指令將需要顯示的字符串從主存復(fù)制到寄存器上,最終顯示在屏幕上
高速緩存至關(guān)重要
前面的三個步驟可以看到,系統(tǒng)進行了大量「復(fù)制」的操作,從一個地方移動到另一個地方,這些在程序設(shè)計角度來說都是開銷,要讓復(fù)制操作盡可能快完成
機械原理說明:
較大的存儲設(shè)備要比較小的存儲設(shè)備運行地慢
高速設(shè)備的制造成本要比低速設(shè)備要高
例如,處理器從磁盤上讀取一個字的時間可能比從主存中讀取的時間要大1000萬倍。同樣寄存器和主存之間的差距也非常大,處理器從寄存器中讀取文件速度也比主存要快100倍
-
處理器與主存之間的差距在持續(xù)增大
-
加快處理器運行速度比加快主存運行速度要容易和便宜
為了處理處理器與主存之間的差異,引入了高速緩存存儲器,存放處理器近期可能會需要的信息,作為暫時的集結(jié)區(qū)域
通過讓高速緩存里存放可能經(jīng)常訪問的數(shù)據(jù),大部分的內(nèi)存操作都能在高速緩存當(dāng)中完成
存儲設(shè)備形成層次結(jié)構(gòu)
在處理器和一個較大較慢的設(shè)備(例如主存)之前插入一個更小更快的存儲設(shè)備(高速緩存)成為一個普遍的概念
每個計算機系統(tǒng)中的存儲設(shè)備都被組織成一個存儲器層次結(jié)構(gòu)
存儲器層次結(jié)構(gòu)的主要思想:上一層的存儲器作為低一層存儲器的高速緩存
操作系統(tǒng)管理硬件
在使用 shell 程序和 hello 程序時候,程序都不是直接訪問鍵盤、顯示器、磁盤或者主存
操作系統(tǒng)是應(yīng)用程序和硬件之間的一層軟件,完成兩個基本功能
防止硬件被失控的應(yīng)用程序濫用
向應(yīng)用程序提供簡單一致的機制來控制復(fù)雜而又通常大不相同的低級硬件設(shè)備
操作系統(tǒng)的抽象
文件是對I/O設(shè)備的抽象
虛擬內(nèi)存是對主存和磁盤I/O設(shè)備的抽象
進程是對處理器、主存和I/O設(shè)備的抽象
進程
進程是操作系統(tǒng)對一個正在運行的程序的一種抽象,在一個系統(tǒng)上可以同時運行多個進程,每個進程都好像是在獨立地使用硬件。
并發(fā)運行,是指一個進程的指令和另一個進程的指令是交錯執(zhí)行的。
一個CPU并發(fā)執(zhí)行多個進程,實際上是通過在處理在進程間切換來實現(xiàn)的,實現(xiàn)這種交錯執(zhí)行的機制為上下文切換
線程
一個進程可以由多個線程組成,每個線程都運行在進程的上下文中,共享同樣的代碼和全局?jǐn)?shù)據(jù)。多線程比多進程之間更容易共享數(shù)據(jù)。
虛擬內(nèi)存
為每個進程提供了一個假象,級每個進程都在獨占地使用主存。每個進程看到的內(nèi)存都是一致的,稱為虛擬地址空間。例如 Linux 虛擬地址空間
-
程序代碼和數(shù)據(jù)
-
堆
運行時動態(tài)地擴展和收縮(調(diào)用malloc和free這樣的C標(biāo)準(zhǔn)庫)
-
共享庫
存放C標(biāo)準(zhǔn)庫和數(shù)學(xué)庫等共享庫
-
棧
編譯器用它來實現(xiàn)函數(shù)調(diào)用,可以動態(tài)擴展和收縮,每調(diào)用一個函數(shù),棧就會增長,每返回一個函數(shù),棧就會收縮
-
內(nèi)核虛擬內(nèi)存
為內(nèi)核保留,不允許程序讀寫或調(diào)用內(nèi)核代碼定義的函數(shù),必須調(diào)用內(nèi)核來執(zhí)行
文件
文件就是字節(jié)序列。每個I/O設(shè)備、磁盤、鍵盤、顯示器、網(wǎng)絡(luò),都可以看成文件
系統(tǒng)的輸入輸出都是調(diào)用稱為 Unix I/O 的系統(tǒng)函數(shù)調(diào)用讀寫文件來實現(xiàn)的
文件為應(yīng)用程序提供了一個統(tǒng)一的視圖,來看待系統(tǒng)中可能含有的各式各樣的I/O設(shè)備
系統(tǒng)之間的利用網(wǎng)絡(luò)通信
從一個單獨的系統(tǒng)來看,網(wǎng)絡(luò)可以視為一個I/O設(shè)備
當(dāng)系統(tǒng)從主存復(fù)制一串字節(jié)到網(wǎng)絡(luò)適配器時,數(shù)據(jù)流經(jīng)過網(wǎng)絡(luò)到達另一臺機器;同樣的,系統(tǒng)可以讀取從其他機器發(fā)送來的數(shù)據(jù),并復(fù)制到自己的主存
重要主題
系統(tǒng)不僅僅是硬件,系統(tǒng)是硬件和系統(tǒng)軟件互相交織的集合體
Amdahl定律
當(dāng)對系統(tǒng)的某個部分加速時,其對系統(tǒng)整體性能的影響取決于該部分的重要性和加速程度
α:系統(tǒng)某部分執(zhí)行時間與整體執(zhí)行時間的比值
k:該部分性能提升的比例
Tnew?=(1?α)Told?+(αTold?)/k=Told?[(1?α)+α/k]T_{\text {new }}=(1-\alpha) T_{\text {old }}+\left(\alpha T_{\text {old }}\right) / k=T_{\text {old }}[(1-\alpha)+\alpha / k] Tnew??=(1?α)Told??+(αTold??)/k=Told??[(1?α)+α/k]
S=ToldTnew=1(1?α)+α/kS=\frac{T_{old}}{T_{new}}=\frac{1}{(1-\alpha)+\alpha / k} S=Tnew?Told??=(1?α)+α/k1?
結(jié)論:想要顯著加速整個系統(tǒng),必須提升全系統(tǒng)中相當(dāng)大的部分的速度
并發(fā)和并行
并發(fā):同時具有多個活動的系統(tǒng)
并行:用并發(fā)來使系統(tǒng)運行地更快
線程級并發(fā)
計算機的并發(fā)是模擬出來的,通過在多個進程之間快速切換實現(xiàn)
可以通過單處理器系統(tǒng) ,也可以通過多處理器系統(tǒng) (多核或超線程)實現(xiàn)
指令集并行
一個處理器可以同時執(zhí)行多條指令,例如流水線
單指令、多數(shù)據(jù)并行
允許一條指令產(chǎn)生多個可以并行的操作
計算機系統(tǒng)中抽象的重要性
所謂抽象,就是類似將一個函數(shù)的內(nèi)部結(jié)構(gòu)進行包裝后形成API對外開放,使得對內(nèi)部無需了解即可使用
總結(jié)
以上是生活随笔為你收集整理的【深入理解计算机系统 01】计算机系统漫游的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android Studio 2.3 打
- 下一篇: 百度seo快排点击系统源码[易语言]拨号