計算機系統漫遊

計算機中的信息

    對於程序員來講,HelloWorld 程序再熟悉不過了,下面是 C 語言寫的 HelloWorld 程序。git

#include<stdio.h>

int main() {
	printf("hello, world\n");
	return 0;
}
複製代碼

    這段程序很簡單,僅僅是在屏幕上輸出hello world,對於程序員很容易閱讀,可是從計算機的角度來看,也是這麼簡單嗎?程序員

    咱們都知道,計算機的世界只有 0 和 1組成的位(比特),這對於人類來講太不友好了,所以計算機科學家們設計了 ASCⅡ 碼來表示現實世界的符號。每 8 個位構成一個組(稱爲一個字節),用一個組來表示一個符號,上面的 C 程序用 ASCⅡ 表示就是下面的樣式。github

image

    所以對於計算機來講,全部的數據都是由一串比特表示的,要區分這些數據對象的惟一方法就是讀到它們時的上下文shell

信息 = 位 + 上下文
複製代碼

源程序編譯

    雖然咱們把 C 語言程序編寫完成了,可是它並不能運行,由於它目前還僅僅是由 ASCⅡ 字符構成的文本文件,計算機並不能運行文本文件。緩存

    想要獲得 HelloWorld 的可執行文件,須要通過預處理、編譯、彙編、連接四個階段。bash

    預處理階段,預處理器會根據以字符#開頭的命令去修改源程序,預處理器去讀取系統頭文件stdio.h中的內容,並將其直接插入程序文本中,結果就獲得了另外一個 C 程序—— hello.i。網絡

    編譯階段,編譯器會把 hello.i 程序翻譯成彙編語言程序 hello.s,彙編語言本質上就是機器語言,此時的程序仍然是文本文件。併發

    彙編階段,彙編器會將 hello.s 翻譯成機器語言指令,保存在 hello.o 文件中,此時獲得的就是二進制文件了。函數

    程序中使用了 printf 函數,這是由編譯器提供的標準 C 庫中的函數,它存儲在 printf.o 文件中,連接器會將這個文件合併到 hello.o 中,結果就獲得一個可執行的 hello 文件,存儲於磁盤中。post

image

系統組成及程序運行

    在運行可執行文件 hello 文件以前,應該先了解一下系統的硬件組成,一個典型系統的硬件組織以下圖所示。

image

    爲了運行 hello 程序,咱們須要在 shell 中輸入指令./hello,指令經過鍵盤經 I/O 總線 --> I/O 橋 --> 總線接口 --> 寄存器 --> I/O 橋存於主存中,當敲擊回車鍵時,等於告訴 shell 程序,命令的屬於已經結束, shell 將會執行一系列指令來加載 hello 文件。

    利用**直接存取(DMA)**技術,hello 文件不須要經過寄存器就能到達主存,當目標文件 hello 到達主存中,處理器就開始執行 hello 程序的機器指令。其指令即將 "hello, world\n" 字符串的字節從主存複製到寄存器,再從寄存器複製到顯示設備中,最終顯示在屏幕上面。

    咱們發現這個簡單的 HelloWorld 程序會讓系統花費大量的時間把信息從一個地方挪到另外一個地方,而咱們都清楚,寄存器、主存、磁盤之間的訪問速度是相互差了好幾個數量級的,而這種複製的開銷會嚴重減慢程序的運行,爲了加快這些複製操做的速度,系統設計者就引入了高速緩存

抽象的重要性

    計算機科學中最爲重要的概念之一就是抽象,指令集提供了對硬件處理器的抽象,操做系統一樣經過進程、虛擬內存、文件(磁盤、鍵盤、網絡均可以當作文件)這幾個抽象概念爲應用程序提供簡單一致的機制來控制低級硬件設備,同時防止硬件被失控的應用程序濫用。

image

    進程是對正在運行的程序的抽象,在一個系統上能夠同時運行多個進程,可是每一個進程看起來都好像在獨佔的使用硬件,CPU 看上去是在併發的執行多個進程,這就須要操做系統進行上下文切換。

    在咱們尚未輸入./hello以前,只有 shell 進程在運行,當咱們讓其運行 hello 程序時,shell 會經過系統調用來執行咱們的請求。操做系統首先保存 shell 進程的上下文(PC、寄存器等信息),而後建立一個新的 hello 進程,並將控制權轉交給 hello 進程。

image
相關文章
相關標籤/搜索