匯編語言:一種用于電子計算機、微處理器矢渊、微控制器,或其他可編程器件的低級語言枉证。在不同的設(shè)備中矮男,匯編語言對應著不同的機器語言指令集。一種匯編語言專用于某種計算機系統(tǒng)結(jié)構(gòu)室谚,而不像許多高級語言毡鉴,可以在不同系統(tǒng)平臺之間移植。使用匯編語言編寫的源代碼秒赤,然后通過相應的匯編程序?qū)⑺鼈冝D(zhuǎn)換成可執(zhí)行的機器代碼猪瞬。這一過程被稱為匯編過程。由于匯編更接近機器語言入篮,能夠直接對硬件進行操作陈瘦,生成的程序與其他的語言相比具有更高的運行速度,占用更小的內(nèi)存潮售,因此在一些對于時效性要求很高的程序痊项、許多大型程序的核心模塊以及工業(yè)控制方面大量應用。(https://zh.wikipedia.org/wiki/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80)
hello程序的生命周期是從一個源程序開始的酥诽,即程序員利用編輯器創(chuàng)建并保存的文本文件鞍泉,文件名是hello.c。源程序?qū)嶋H上就是個由值0和1組成的位(bit)序列肮帐。8個位被組織成一組咖驮,稱為字節(jié)。每個字節(jié)表示程序中的某個文本字符。大部分的現(xiàn)代系統(tǒng)都使用ASCII標準來表示文本字符游沿,這種方式實際上就是用一個唯一的單字節(jié)大小的整數(shù)值來表示每個字符饰抒。
像hello.c這樣只由ASCII字符構(gòu)成的文件稱為文本文件,所有其他文件都稱為二進制文件诀黍。
系統(tǒng)的所有信息——包括磁盤文件袋坑,存儲器中的程序、存儲器中存放的用戶數(shù)據(jù)以及網(wǎng)絡(luò)上傳送的數(shù)據(jù)眯勾,都是由一連串位表示的枣宫。區(qū)分不同數(shù)據(jù)對象的唯一方法是我們讀到這些數(shù)據(jù)對象時的上下文。比如吃环,在不同的上下文中怜械,一個同樣的字節(jié)序列可能表示一個整數(shù)添履、浮點數(shù)拟杉、字符串或者機器指令笑旺。
C語言與Unix操作系統(tǒng)關(guān)系密切。Unix幾乎全部都是用C編寫的好唯,所以可以很方便地移植到新的機器上竭沫,這種特點為C和Unix贏得了更為廣泛的支持。C語言的指針是造成困惑和程序錯誤的一個常見原因骑篙。同時蜕提,C還缺乏對非常有用的抽象(例如類、對象和異常)的顯式支持靶端。Cpp和Java這樣針對應用級程序的新程序設(shè)計語言解決了這些問題谎势。
hello程序的生命周期是從一個高級C語言程序開始的,因為這種形式能夠被人讀懂杨名。然后脏榆,為了在系統(tǒng)上運行hello.c,每條C語句都必須被其他程序轉(zhuǎn)化為一系列的低級機器語言指令镣煮。然后這些指令按照一種可執(zhí)行目標程序的格式打好包姐霍,并以二進制磁盤文件的形式存放起來鄙麦。目標程序也稱為可執(zhí)行目標文件典唇。
unix> gcc -o hello hello.c
預處理階段-預處理器(cpp)根據(jù)以字符#開頭的命令,修改C的原始程序胯府。#include<stdio.h>告訴預處理器讀取系統(tǒng)頭文件stdio.h的內(nèi)容介衔,并把它插入到程序文本中,結(jié)果得到另一個C程序骂因,通常以.i作為文件擴展名炎咖。
編譯階段-編譯器(ccl)將hello.i轉(zhuǎn)換為匯編語言程序。不同語言編譯器產(chǎn)生的輸出文件用的都是一樣的匯編語言。
匯編階段-匯編器(as)將hello.s翻譯成機器語言指令乘盼,把這些指令打包成可重定位目標程序(relocatable object program)的格式升熊,并將結(jié)果保存在hello.o中,一個二進制文件绸栅,其字節(jié)編碼是機器指令而不是字符级野,如果在文本編輯器中打開hello.o,看到的將是一堆亂碼粹胯。
鏈接階段-printf函數(shù)存在于一個名為printf.o的單獨的預編譯好了的目標文件中蓖柔,而這個文件必須以某種方式合并到hello.o程序中。鏈接器(ld)就負責處理這種合并风纠。結(jié)果得到hello文件况鸣,一個可執(zhí)行目標文件,可以被加載在內(nèi)存中竹观,由系統(tǒng)執(zhí)行镐捧。
unix> ./hello
Shell(外殼)是一個命令行解釋器,它輸入一個提示符臭增,等待你輸入一個命令行愤估,然后執(zhí)行這個命令。如果該命令行的第一個單詞不是一個內(nèi)置的外殼命令速址,那么外殼就會假設(shè)這是一個可執(zhí)行文件的名字玩焰,它將加載并運行這個文件。
系統(tǒng)硬件組成
1.總線:貫穿整個系統(tǒng)的一組電子管道芍锚。攜帶信息字節(jié)并負責在各個部門間傳遞昔园。通常總線被設(shè)計成傳送定長的字節(jié)塊并炮,也就是字(word)默刚。字中的字節(jié)數(shù)(即字長)是一個基本的系統(tǒng)參數(shù),各個系統(tǒng)不盡相同逃魄,大多數(shù)是四個字節(jié)(32位)/八個字節(jié)(64位)荤西。為討論方便,假設(shè)字長為4個字節(jié)伍俘,并且總線每次只傳送一個字邪锌。
2.I/O設(shè)備:輸入/輸出設(shè)備是系統(tǒng)與外部世界的聯(lián)系通道。示例中的包括——作為用戶輸入的鍵盤和鼠標癌瘾,作為用戶輸出的顯示器觅丰,以及用于長期存儲數(shù)據(jù)和程序的磁盤驅(qū)動器(即磁盤)。最初妨退,可執(zhí)行程序hello就存放在磁盤上妇萄。每個I/O設(shè)備都通過一個控制器或適配器與I/O總線相連蜕企。控制器和適配器之間的區(qū)別主要在于其封裝方式冠句。控制器是置于I/O設(shè)備本身的或者系統(tǒng)的主印制電路板(主板)上的芯片組轻掩,而適配器則是一塊插在主板插槽上的卡。其功能都是在I/O總線和I/O設(shè)備之間傳遞信息懦底。
3.主存:一個臨時存儲設(shè)備放典。在處理器執(zhí)行程序時,用來存放程序和程序處理的數(shù)據(jù)基茵。物理上說奋构,是由一組動態(tài)隨機存取存儲器DRAM芯片組成的。邏輯上說拱层,存儲器是一個線性數(shù)組弥臼,每個字節(jié)都有其唯一的地址(即數(shù)組索引),這些地址從0開始根灯。一般而言径缅,組成程序的每條機器指令都由不同數(shù)量的字節(jié)構(gòu)成。與C程序變量相對應的數(shù)據(jù)項的大小是根據(jù)類型變化的烙肺。例如纳猪,在運行Linux的IA32機器上,short類型的數(shù)據(jù)需要2個字節(jié)桃笙,int氏堤、float和long類型需要4個字節(jié),double類型需要8個字節(jié)搏明。
4.處理器(CPU):即中央處理單元鼠锈,是解釋(或執(zhí)行)存儲在主存中指令的引擎。處理器的核心是一個字長的存儲設(shè)備(或寄存器)星著,稱為程序計數(shù)器(PC)购笆。在任何時刻,PC都指向主存中的某條機器語言指令(即含有該條指令的地址)虚循。從系統(tǒng)通電開始直到斷電同欠,處理器一直在不斷執(zhí)行PC指向的指令,再更新PC横缔,使其指向下一條指令铺遂。處理器按照非常簡單的指令執(zhí)行模型來操作,這個模型是由指令集結(jié)構(gòu)決定的剪廉。在這個模型中娃循,指令按照嚴格的順序執(zhí)行,而執(zhí)行一條指令包含一系列的步驟斗蒋。處理器按照PC指向的存儲器處讀取指令捌斧,解釋指令中的位,執(zhí)行該指令指示的簡單操作泉沾,然后更新PC捞蚂,而這條指令并不一定和存儲器中剛剛執(zhí)行的指令相鄰。然而并非所有操作都是簡單如此跷究,大多數(shù)操作圍繞著主存姓迅、寄存器文件(register file)和算數(shù)/邏輯單元(ALU)進行。寄存器文件是一個小的存儲設(shè)備俊马,由一些1字長的寄存器組成丁存,每個寄存器都有唯一的名字。ALU計算新的數(shù)據(jù)和地址值柴我。一些操作如加載(把一個字節(jié)/字從主存復制到寄存器解寝,以覆蓋寄存器原來的內(nèi)容),存儲(把一個字節(jié)/字從寄存器復制到主存的某個位置艘儒,以覆蓋這個位置原來的內(nèi)容)聋伦,操作(把兩個寄存器的內(nèi)容復制到ALU,令ALU對這兩個字做算術(shù)操作界睁,并將結(jié)果存放到一個寄存器中覆蓋原先內(nèi)容)觉增,跳轉(zhuǎn)(從指令本身抽取一個字,并將這個字復制到PC中翻斟,以覆蓋PC中原來的值)逾礁。指令集結(jié)構(gòu)描述的是每條極其代碼指令的結(jié)果,而微體系結(jié)構(gòu)描述的是處理器實際上如何實現(xiàn)访惜。
高速緩存存儲器:為解決處理器和主存之間的差異所用的更小更快的存儲設(shè)備所用的敞斋,作為暫時的集結(jié)區(qū)域,以存放處理器近期可能會需要的信息疾牲。達到數(shù)萬字節(jié)的L1高速緩存植捎,訪問速度幾乎和訪問寄存器一樣快,其使用的是靜態(tài)隨機訪問存儲器(SRAM)的硬件技術(shù)實現(xiàn)的阳柔。
操作系統(tǒng):可以看作是應用程序和硬件之間的一層軟件焰枢。所有應用程序?qū)τ布牟僮鲊L試都必須通過操作系統(tǒng)。操作系統(tǒng)的基本功能1)防止硬件被失控的應用程序濫用;2)向應用程序提供簡單一致的機制來控制復雜又通常大相徑庭的低級硬件設(shè)備舌剂。
進程:操作系統(tǒng)對一個正在運行的程序的一種抽象济锄。在一個系統(tǒng)上可以同時運行多個進程,而每個進程都好像在獨占地使用硬件霍转。而并發(fā)運行荐绝,是指一個進程的指令和另一個進程的指令是交錯執(zhí)行的。傳統(tǒng)系統(tǒng)在一個時刻只能執(zhí)行一個程序避消,而先進的多核處理器可以同時執(zhí)行多個程序低滩。無論是單核還是多核系統(tǒng)中召夹,一個CPU看上去都像是在并發(fā)地執(zhí)行多個進程,這是通過處理器在進程間切換實現(xiàn)的恕沫。操作系統(tǒng)實現(xiàn)這種交錯執(zhí)行的機制稱為上下文切換监憎。操作系統(tǒng)保持跟蹤進程運行所需的所有狀態(tài)信息,這種狀態(tài)即上下文婶溯,包括許多信息鲸阔,如PC和寄存器文件的當前值,以及主存的內(nèi)容迄委。
線程:盡管通常我們認為進程只有單一的控制流褐筛,但在現(xiàn)代系統(tǒng)中,一個進程實際上可以由多個稱為線程的執(zhí)行單元組成叙身,每個線程都運行在進程的上下文中渔扎,并共享同樣的代碼和全局數(shù)據(jù)。由于網(wǎng)絡(luò)服務器對并行處理的需求曲梗,線程成為越來越重要的編程模型赞警,因為多線程之間比多進程間更容易共享數(shù)據(jù),也因為線程一般都比進程更高效虏两。當有多處理器可用的時候愧旦,多線程也是一種使程序可以更快運行的辦法。
虛擬存儲器:是一個抽象概念定罢,它為每個進程提供了一個假象笤虫,即每個進程都在獨占地使用內(nèi)存。每個進程看到的是一致的存儲器祖凫,稱為虛擬地址空間琼蚯。Linux中,地址空間最上面的區(qū)域是為操作系統(tǒng)中的代碼和數(shù)據(jù)保留的惠况,這對所有進程都是一樣的遭庶。地址空間的底部區(qū)域存放用戶進程定義的代碼和數(shù)據(jù)。
程序代碼和數(shù)據(jù):對所有進程來說稠屠,代碼是從同一固定地址開始峦睡,緊接著的是和C全局變量相對應的數(shù)據(jù)位置。代碼和數(shù)據(jù)區(qū)是直接按照可執(zhí)行目標文件的內(nèi)容初始化的权埠,在示例中就是可執(zhí)行文件hello榨了。
堆:代碼和數(shù)據(jù)區(qū)后緊隨著的是運行時堆。代碼和數(shù)據(jù)區(qū)在一開始運行時就被規(guī)定了大小攘蔽,與此不同龙屉,當調(diào)用如malloc和free這樣的C標準庫函數(shù)時,堆可以在運行時動態(tài)地擴展和收縮满俗。
共享庫:在地址空間約中間部分是一塊用于存放像C標準庫和數(shù)學庫這樣共享庫代碼和數(shù)據(jù)的區(qū)域转捕。
棧:用于編譯器實現(xiàn)函數(shù)調(diào)用作岖。和堆一樣在程序執(zhí)行期間可動態(tài)擴展和收縮。每次調(diào)用一個函數(shù)時瓜富,棧會增長鳍咱。從一個函數(shù)返回時降盹,棧會收縮与柑。
內(nèi)核虛擬存儲器:內(nèi)核總是駐留在內(nèi)存中,是操作系統(tǒng)的一部分蓄坏。地址空間頂部區(qū)域是為內(nèi)核保留的价捧,不允許應用程序讀寫這個區(qū)域的內(nèi)容或直接調(diào)用內(nèi)核代碼定義的函數(shù)。
文件:即字節(jié)序列涡戳。每個I/O設(shè)備结蟋,包括磁盤、鍵盤渔彰、顯示器嵌屎、網(wǎng)絡(luò),都可視為文件恍涂。系統(tǒng)中所有輸入輸出都是通過使用一小組稱為Unix I/O的系統(tǒng)函數(shù)調(diào)用讀寫文件實現(xiàn)的宝惰。
并發(fā)(concurrency)和并行(parallelism):并發(fā)指一個同時具有多個活動的系統(tǒng),并行指的是用并發(fā)使一個系統(tǒng)運行更快再沧。
超線程(hyperthreading):有時稱為同時多線程(simultaneous multi-threading)尼夺,是一項允許一個CPU執(zhí)行多個控制流的技術(shù)。涉及CPU某些硬件有多個備份炒瘸,比如程序計數(shù)器和寄存器文件淤堵,而其它硬件部分只有一份,如執(zhí)行浮點算術(shù)運算的單元顷扩。常規(guī)處理器需要約20000個時鐘周期做不同線程間的轉(zhuǎn)換拐邪,而超線程的處理器可以在單個周期的基礎(chǔ)上決定要執(zhí)行哪一個線程,這使得CPU能夠更好地利用它的處理資源隘截。
指令集并行:在較低的抽象層次上扎阶,現(xiàn)代處理器可以同時執(zhí)行多條指令的屬性。如果處理器可以達到比一個周期一條指令更快的執(zhí)行效率技俐,就稱之為超標量(superscaler)處理器乘陪。
單指令、多數(shù)據(jù)并行:在最低層次上雕擂,許多現(xiàn)代處理器擁有特殊的硬件啡邑,允許一條指令產(chǎn)生多個可以并行執(zhí)行的操作,即SIMD并行井赌。提供SIMD指令多是為了提高處理影像谤逼、聲音和視頻數(shù)據(jù)應用的執(zhí)行速度贵扰。雖然有些編譯器試圖從C程序中自動抽取SIMD并行性,但更可靠的方法是使用編譯器支持的特殊向量數(shù)據(jù)類型來寫程序流部。