计算机程序是怎样运行的-hello world程序运行原理
關于《深入理解計算機系統》
“這本書的中譯名為“深入理解計算機系統”,我非常,十分,以及百分之一百二十地不滿意。我這么說的原因在于這個譯法完全扭曲了書的本意。如果直譯原書名,應該是類似于“以程序員的視角理解計算機系統”,何來“深入”二字。可能在國內編輯看來,這是講系統的,用C和匯編語言的,因此很“深入”,但我認為這只能說明國內技術氛圍的淺薄。因為事實上,這是一本入門級別的書,這本書其實并不“深入”,它談論的內容還是相對比較淺的。但“淺”不代表“淺薄”,寫一本面向初學者的好書往往是非常困難的,因此無論是SICP還是CSAPP,它的作者都是頂尖學府的教授,結合多年教學經驗而寫出來的。
CMU把這本書作為“Introduction?to?Computer?System”課程的教材,是面向計算機專業低年級學生的“計算機系統介紹(導論)”,可能這些學生只是剛剛了解如何使用一門高級語言——如Java進行編程,對于計算機系統的工作方式等話題可謂一點都沒有接觸過,而CSAPP對讀者的背景也只要求是“一些編程經驗”而已。這本書的話題覆蓋面很廣,從計算機的基本組成,二進制數據表示方式,到機器級別的指令,CPU工作方式,存儲結構和優化,操作系統的虛擬內存管理,程序運行方式,I/O,網絡、到(較底層)程序性能優化和并行程序開發等等。所以,它其實覆蓋了“計算機組成原理”,“操作系統”等許多課程的內容,其中的許多話題都能再次展開,繼續深入,都能再變成一本,甚至N本經典。事實上,在高年級的計算機專業課程設置中,都會有更加縱向的內容出現。” ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ——摘自Jeffrey?Zhao博文
老趙的這一番話,深深的觸動了我,確實,這本書用怎么說呢,并不是深入,而是涉及的知識比較廣,但又都是廣大程序猿不得不知道的知識,下面我們就來慢慢品嘗這本書吧。工作之余,學習學習,總是好的。言歸正傳,接下來,享讀《Computer?Systems:?A?Programmer’s?Perspective》的中hello world程序都干了些啥。
?
1.信息在計算機的中表示
當我們輸入以下程序,編譯運行,計算機從屏幕輸出hello,?world。整個過程計算機都怎么運作的呢?
#include?<stdio.h>
int?main()
{
printf("hello,?world\n");
}
我們知道,信息在計算機中都是用0或1表示的。計算機通過這些位信息以及上下文來解讀這些0/1。也即:計算機中的信息=位+上下文。
我們輸入的hello程序就是由0、1組成的序列,將這些位8位組織成一個字節,每個字節用來表示一個文本字符。ASCII碼給出了一種字符與數字的一一對應關系。
hello,?world程序以字節方式存放于文件中,如下圖所示。其每個字符對應一個數字,具體可參考ASCII碼表。
圖1?Hello?world程序的ASCII碼表示
2.將程序翻譯成機器可讀的格式
因為我們輸入的hello,?world程序是人可讀的,機器并不能直接識別它們。我們需要把這些文字翻譯成機器可執行的二進制文件。這一部分的工作是由編譯系統完成的。編譯系統由預處理器、編譯器、匯編器、連接器四部分組成。以hello,?world程序為例,各部分共同完成將源文件編譯成二進制可執行文件。各個部分完成的具體工作如下:
l?預處理器:根據以#開頭的命令,修改源程序。如根據#include?<stdio.h>行,預處理器讀取系統頭文件stdio.h中的內容,代替此行內容。源程序經過預處理后,得到另一個c程序,此程序通常以.i為后綴保存。
l?編譯器:將預處理后的.i文件轉換成匯編程序。編譯器將不同的高級語言(如c語言,C++語言)轉換成嚴格一致的匯編語言格式進行輸出。匯編語言以標準的文本格式確切的描述每機器語言指令。編譯器得到的文件通常以.s為后綴保存。
l?匯編器:將匯編語言(.s文件)翻譯成機器語言指令,并將這些指令打包成一種可定位目標程序格式。匯編后得到的文件即為二進制文件,通常以.o為后綴。
l?鏈接器:hello,?world程序中調用過printf函數,它是一個c標準庫里的函數。Printf函數存放在一個名為printf.o的單獨預編譯的文件中。而這個文件必須以適當的方式并入到我們的程序中,這個工作由鏈接器完成。將外部的.o文件并入后,得到一個完整的hello,?world可執行文件??蓤绦形募虞d到存儲器后,由系統復制執行。
圖2?編譯系統
在linux系統上,輸入編譯命令行:
Viidiot>gcc?hello.c?-o?hello
將執行上圖所示的四個步驟,得到可執行二進制文件hello。
3.處理器讀取并解釋存儲在存儲器中的指令
Shell:命令行解釋器,為用戶提供了一只與系統打交道的方式。它等待用戶的輸入,當用戶輸入一行命令后,shell先判斷它是不是一個shell內置命令,如果不是,shell會假定用戶輸入為一個可執行文件的名字,從而去加載并執行該文件。因此,當我們通過編譯系統將源文件編譯成可執行二進制文件后,在shell中輸入我們得到的可執行二進制文件名,shell將其從磁盤中加載到存儲器(注:我們的可執行文件是存放在磁盤上的),并通過處理器進行解釋執行,得到最終的結果,輸出到終端(顯示器)上進行顯示。自此,我們的hello,?world程序完成了其生命周期。
4.計算機系統硬件結構
為了弄清楚hello,?world運行時,系統究竟發生了什么,我們先來了解下一個典型的計算機硬件結構。
圖3?典型的計算機硬件構成
【CPU:中央處理器???ALU:算術/邏輯運算單元??PC:程序計數器??USB:統一串行接口】
?
下面簡單說一下各個部件在系統中所起的作用。
總線:在各個部件之間傳輸數據?,F在的總線寬度一般為32位或者64位,即一次傳輸的數據為4字節或者8字節。
I/O設備:IO設備是系統與外界通信的通道,如鼠標,鍵盤,顯示器都是典型的IO設備。
主存儲器:簡稱主存,是處理器執行程序時用于臨時存放程序及其數據。主存由一組動態隨機存儲器芯片組成。
處理器:解釋執行存儲在主存中的指令。其內部包含一個雙字節程序計數器(PC),任何時候PC中都存放著接下來要執行的機器指令在主存中的地址。
處理器的操作主要是圍繞PC、ALU、主存來進行運作的。處理器首先從PC所指向的主存存儲單元讀取指令,解釋指令中的位,執行該指令指示的簡單操作,然后更新PC寄存器,使其指向下一條要執行的指令。CPU會執行的操作有:
加載:把一個字節或一個字從主存復制到寄存器,覆蓋掉寄存器中原來的值。
存儲:把一個字節或一個從寄存器復制到主存,并覆蓋主存中原來的值。
操作:把兩個寄存器的內容復制到ALU,ALU對兩個字做算術運算后存回其中的一個寄存器,該寄存器中原來的值會被覆蓋。
跳轉:從cpu執行的指令抽取一個字的內容存入PC,覆蓋掉原來的值,從而改變下一條要執行的指令,達到跳轉的目的。
在了解了一些基本的硬件結構,以及各個部分的作用后,我們再來看看之前的hello,?world程序的運行過程。
圖4?加載可執行文件到主存的過程
在linux系統下,我們在shell中敲入以下命令
Viidiot>./hello
由于shell沒有內置hello命令,因此shell將我們輸入的hello視為一個可執行文件,從而通過執行一系列機器指令,將可執行文件hello從磁盤復制到主存,如圖4所示。
注意,如果通過DMA方式加載程序,則不需要通過CPU,而是將hello可執行文件直接從磁盤復制到主存,示意圖如圖5。
圖5?DMA方式加載程序到主存
?
可執行程序加載到主存后,cpu就執行hello程序的機器指令,而這些指令完成的工作便是將”hello,world\n”這幾個字符從主存中復制寄存器文件中(register?file),再將其從寄存寄文件中復制到顯示設備上進行顯示。過程示意圖如圖6所示。
圖6??cpu執行指令,將?“hello,world\n”從內存復制到顯示設備
至此,hello,world程序的執行過程已經完成。
題外話:
從上面的程序實例我們可以看到,程序花費了大量的時間將數據從一個部件復制到另外一個部件。程序加載時,將hello程序的機器指令從磁盤復制到主存,程序運行時,又將其從主存復制到cpu,最后又從cpu復制到外部顯示器。將根據機械原理,大容量的存儲設備速度比小容量存儲設備慢,快速設備的造價比慢速設備的造價高。對于計算機硬件系統,CPU的速度遠高于主存的速度,而主存的速度遠高于磁盤,不同部件的速度嚴重不對等,從而快的設備的性能沒能得到充分發揮。為解決各類設備速度不匹配的問題,引入了高速緩存設備來緩解速度匹配問題。如圖7所示,為加入了高速緩存后的系統部分結構。
圖7?高速緩存存儲器
現代計算機為提高系統性能,一般都加入了多級緩存結構。高速緩存采樣的是靜態隨機存儲器硬件(SRAM)技術,速度快于主存(采樣動態隨機存儲器技術)。如圖8是存儲器結構金字塔,越往上速度越快,造價也更昂貴。
圖8?存儲器金字塔
作者:Viidiot(阿呆)? 轉載請保留作者及鏈接
總結
以上是生活随笔為你收集整理的计算机程序是怎样运行的-hello world程序运行原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言程序-hello world-运行
- 下一篇: C/C++内存分配方式与存储区