以hello
程式為例來解釋程式的生命週期,hello.c
檔案程式碼如下:
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
為了在系統上執行 hello.c
程式,檔案中的每條 C 語言都必須被其他程式轉化為一系列的低階機器語言指令。然後這些指令按照一種稱為可執行目標程式的格式打包好,並以二進位制磁碟檔案的形式儲存。目標程式也稱為可執行目標檔案。
在 Linux 系統中,GCC
編譯器將源程式檔案 hello.c 翻譯(編譯)為目標檔案 hello 的過程分為四個階段,如下圖所示。執行這四個階段(前處理器、編譯器、組合器和連結器)的程式一起構成了編譯器系統(compilation system)。
典型系統的硬體組織構成: 匯流排、I/O
裝置、主記憶體(動態隨機存取存取器 DRAM
)、處理器。
主記憶體是臨時儲存裝置,在處理器執行程式時,用來存放程式和程式處理的資料。從邏輯上說,記憶體是一個線性的位元組陣列,每個位元組都有其唯一的地址(陣列索引),這些地址是從零開始的。
將 hello 程式輸出的字串從記憶體寫到顯示器的過程如下圖所示。
針對處理器與主記憶體之間讀取資料的差異,處理器系統設計者採用了更小更快的儲存裝置,稱為高速緩衝器(cache memory,簡稱 cache 或高速緩衝),作為暫時的集結區域,存放處理器近期可能會需要的資訊。
在處理器和一個較大較慢的裝置(例如主記憶體)之間插入一個更小更快的儲存裝置(例如高速緩衝)的想法已經成為一個普遍的觀念。實際上,每個計算機系統中的儲存裝置都被組織成了一個記憶體層次結構,如圖1-9所示。在這個層次結構中,從上至下,裝置的存取速度越來越慢、容量越來越大,並且每位元組的成本也越來越低。
所有應用程式對硬體的操作嘗試都必須通過作業系統,作業系統有兩個基本功能:
作業系統通過幾個基本的抽象概念(程序、虛擬記憶體和檔案)來實現這兩個功能。檔案是對 I/O 裝置的抽象表示,虛擬記憶體是對主記憶體和磁碟 I/O 裝置的抽象表示,程序則是對處理器、主記憶體和 I/O 裝置的抽象表示。
程序是作業系統對一個正在執行的程式的一種抽象。在一個系統上可以同時執行多個程序,每個程序都好像在獨佔地使用硬體。而並行執行,則是說一個程序的指令和另一個程序的指令是交錯之行的。在大多數系統中,需要執行的程序數是可以多於它們的 CPU
個數的。無論在單核還是多核系統中,一個 CPU
看上去都像是在並行地執行多個程序,這實際是通過處理器在程序間切換來實現的,作業系統實現這種交錯執行的機制成為上下文切換。
作業系統會保持跟蹤程序執行所需的所有狀態資訊,這種狀態資訊稱為上下文,其包括多種資訊,比如 PC
和暫存器檔案的當前值,以及主記憶體的內容。在任何一個時刻,但處理器系統都只能執行一個程序的程式碼。當作業系統決定要把控制權從當前程序轉移到某個新程序時,就會進行上下文切換,即儲存當前程序的上下文、恢復程序的上下文,然後將控制權傳遞到新程序。圖1-12展示了範例 hello 程式執行場景的基本理念。
儘管我們直觀認為一個程序只有單一的控制流,但在現代計算機系統中,一個程序實際上可以由多個稱為執行緒的執行單元組成,每個執行緒都執行在程序的上下文中,並共用同樣的程式碼和全域性資料。由於網路伺服器對並行處理的需求,執行緒成為越來越重要的程式設計模型,因為多執行緒之間比多程序之間更容易共用資料且更高效。
虛擬記憶體是一個抽象概念,它為每個程序提供了一個假象,即每個程序都在獨佔地使用主記憶體,每個程序看到的記憶體都是一致的,稱為虛擬地址空間。圖 1-13 所示的是 Linux 程序的虛擬地址空間。在 Linux 中,地址空間最上面的區域是保留給作業系統中程式碼和資料的,這對所有程序來說都是一樣。地址空間的底部區域存放使用者程序定義的程式碼和資料。注意,圖中的地址從下往上增大的。
每個程序看到的虛擬地址空間由大量準確定義的區構成,每個區都有專門的功能,程序的虛擬地址空間意義如下。
malloc
和 free
這樣的 C 標準庫函數時,堆可以在執行時動態地拓展和收縮。虛擬記憶體的運作需要硬體和作業系統軟體之間精密複雜的互動,包括對處理器生成的每個地址的硬體翻譯,基本思想是把一個程序虛擬記憶體的內容存在在磁碟上,然後用主記憶體作為磁碟的高速緩衝。
檔案就是位元組序列,每個 I/O 裝置包括磁碟、鍵盤、顯示器,甚至網路都可以看成檔案,系統中所有輸入輸出都是通過使用一小組稱為 Unix I/O 的系統函數呼叫讀寫檔案來實現的。
現代系統通過網路將單個計算機系統連線在一起。
該定律的主要思想就是,當我們對系統的某個部分加速時,其對系統整體效能的影響取決於該部分的重要性和加速程度。
我們用術語並行(concurrency
)是一個通用的概念,指一個同時具有多個活動的系統;而術語並行(parallelism
)指的是用並行來是一個系統執行得更快。並行可以在計算機系統的多個抽象層次上運用,這裡按照系統層次結構中由高到低的順序描述三個層次。
1,執行緒級並行
超執行緒,有時稱為同時多執行緒(simultaneous multi-threading),是一項允許一個 CPU
執行多個控制流的技術。它涉及 CPU 某些硬體有多個備份,比如程式計數器和暫存器檔案,而其他硬體部分只有一份,比如執行浮點算術運算的單元。常規的處理器需要大約 20000 個時鐘週期做不同執行緒間的轉換,而超執行緒的處理器可以在單個週期的基礎上決定要執行哪一個執行緒。
多處理器的使用可以從兩方面提高系統效能,首先,它減少了在執行多個任務時模擬並行的需要;其次,它可以使應用程式執行得更快,前提是程式以多執行緒方式編寫。
2,指令級並行
在較低的抽象層次上,現代處理器可以同時執行多條指令的屬性稱為指令級並行。如果處理器可以達到比一個週期一條指令更快的執行速率,就稱為超標量(super-scalar)處理器,大多數現代處理器都支援超標量操作。
3,單指令、多資料並行
在最低層次中,許多現代處理器擁有特殊的硬體,允許一條指令產生多個可以並行執行的操作,這種方式稱為單指令、多資料,即 SIMD
並行。
前面我們介紹了計算機系統使用的幾個抽象,如圖 1-18 所示,在處理器裡,指令集架構提供了對實際處理器的抽象。
作業系統中有四個抽象:檔案是對 I/O 裝置的抽象,虛擬記憶體時對程式記憶體的抽象,程序是對一個正在執行的程式的抽象,虛擬機器器提供對整個計算機的抽象,包括作業系統、處理器和程式。