然而,對於這樣壹個極其簡單的程序,有許多問題是模糊的。例如,用C語言寫的:
本文將集中討論上述問題。
從軟件開發者的角度來說,我們需要知道計算機硬件最關鍵的三個部件:CPU、內存和I/O控制芯片。
早期CPU的核心頻率並不高,就像內存頻率壹樣,都是直接連在同壹條總線上。由於顯示設備、鍵盤、軟盤、磁盤等I/O設備的速度仍然比CPU和內存慢得多,為了協調I/O設備和總線的速度,並使CPU能夠與I/O設備通信,每個設備壹般都有相應的I/O控制器。如下圖所示:
後來由於CPU核心頻率提高,內存跟不上CPU的速度,於是產生了內存頻率相同的系統總線,CPU通過倍頻的方式與總線通信。
然後,隨著圖形操作系統的普及,尤其是SD遊戲和多媒體的發展,圖形芯片需要與CPU和內存交換大量的數據。為了協調,專門設計了壹個高速北橋(PCI橋)芯片,以便它們可以高效地交換數據。
因為北橋運行速度非常高,如果所有相對低速的設備都直接連接到北橋,那麽北橋既要處理高速設備,又要處理低速設備,設計會非常復雜。因此,人們設計了壹種南橋芯片來處理低速設備。磁盤、USB、鍵盤、鼠標等設備都接入南橋,由南橋匯總後接入北橋。90年代PC在系統總線上使用PCI結構,低速設備上使用ISA總線,用PCI/ISA和南北橋設計的硬件架構如下:
位於中間的是連接所有高速芯片的北橋,它就像人的心臟,連接和驅動身體的各個部分;它的左邊是CPU,負責所有的控制和計算,就像人腦壹樣。北橋還連接了幾個高速部件,包括左邊的內存和下面的PCI總線。
PCI的最高速度是133 MHz,但仍然不能滿足人們的需求,於是人們發明了AGP、PCI Express等多種總線結構和相應的控制芯片。雖然硬件結構看起來越來越復雜,但實際上仍然沒有脫離原來的CPU、內存、I/O的基本結構,當我們從程序開發的角度來看硬件時,可以簡單地把它看成是原來的硬件模型。
人們總是希望計算機越快越好。50年來,CPU的頻率從幾十kHz提升到4GHz,提升了幾十萬倍。但此後壹直沒有質的提升,因為CPU的制造工藝已經到了物理極限,除非CPU的制造工藝有本質的突破。
頻率已經沒有提升的空間了,所以反過來說,提升速度就是增加CPU的數量。很久以前就出現了多CPU的計算機,最常見的形式是對稱多處理(SMP),簡單來說就是每個CPU在系統中的位置和功能都是相同的,並且彼此對稱。
理論上,增加CPU的數量可以提高運算速度,理想情況下,速度的提高與CPU的數量成正比。但實際上並不是這樣,因為我們的程序並不是都能分解成幾個完全不相關的子問題。比如女人10個月可以生孩子,但是10個月不能生孩子。
多處理器最常見的應用也是這些需要處理大量計算的商業服務器和環境。在個人電腦中,使用多個處理器是壹種奢侈。畢竟多處理器成本很高。
於是處理器廠商開始考慮“合並多個處理器,打包出售”。這些“打包”的處理器共用昂貴的緩存組件,只保留多個內核,放在壹個處理器的外包裝中出售,只比單核處理器貴壹點點。這是多核處理器的基本思想。多核處理器實際上是SMP的簡化版本。當然在細節上有壹些差異,但是從程序員的角度來看,兩者的差異是很小的,邏輯上是完全壹樣的。只是多核和SMP在緩存共享上有細微的區別,使得程序在優化上可以有針對性的處理。簡單來說,除非妳想榨幹CPU的每壹滴,否則妳可以把多核和SMP當成同壹個概念。
用於管理計算機本身的軟件稱為系統軟件,以區別於普通的應用程序。
系統軟件分為兩大類,壹類是平臺,比如操作系統、內核、驅動、運行時以及成千上萬的系統工具,另壹類是用於程序開發的,比如編譯器、匯編器、連接器等開發工具和庫。
計算機系統的軟件系統采用層的結構,有壹句名言:
這句名言概括了計算機系統軟件架構的設計要點,整個架構嚴格按照自上而下的層次結構進行設計。
操作系統的壹個功能是提供抽象接口,另壹個主要功能是管理硬件資源。
計算機硬件的能力是有限的。例如,CPU每秒可以執行65,438+0億條指令,或者65,438+0 GB內存可以同時存儲多達65,438+0 GB的數據。不管妳用不用,資源總是那麽多。
計算機中的資源主要分為CPU、內存(包括內存和磁盤)和I/O設備。我們從這三個方面來看看如何挖掘他們的潛力。
操作系統作為硬件層的上層,是對硬件的管理和抽象。對於操作系統上的運行時和應用,他們希望看到的是統壹的硬件訪問模式。作為應用開發者,我們在開發應用時,不希望直接讀寫硬件端口,處理硬件中斷。例如,我們想在顯示器上畫壹條直線。對於程序員來說,只需調用壹個統壹的LineTo()函數,具體實現方法由操作系統完成。
當壹個成熟的操作系統出現後,硬件逐漸被抽象成壹系列概念。在UNIX中,硬件設備的訪問形式與普通文件的訪問形式相同。這些繁瑣的硬件細節都交給了操作系統,具體來說就是操作系統中的設備驅動程序。驅動程序可以看作是操作系統的壹部分,它往往和操作系統內核壹起運行在特權級,但又在壹定程度上獨立於操作系統內核,使得驅動程序更加靈活。
早期的計算機,程序直接運行在物理內存上,也就是程序運行時訪問的地址都是物理地址。當然,如果壹臺計算機同時只運行壹個程序,只要程序需要的內存空間不超過物理內存的大小,就不會有問題。但實際上,為了更有效地利用硬件資源,我們必須同時運行多個程序,就像以前的多程序、分時系統、多任務壹樣。當我們可以同時運行多個程序時,CPU的利用率會更高。那麽壹個顯而易見的問題就是如何將電腦上有限的物理內存分配給多個程序。
存在的問題有:
地址空間不是隔離的:所有的程序都直接訪問物理地址,程序使用的內存空間也不是相互隔離的。
內存使用效率低:由於沒有有效的內存管理機制,當壹個程序需要執行時,監控程序會將整個程序加載到內存中,然後開始執行。
程序運行的地址是不確定的:因為每次程序需要加載運行時,我們都需要從內存中分配壹個足夠大的空閑區域,而這個空閑區域的位置是不確定的。
虛擬地址空間指的是虛擬的和想象的地址空間。事實上,它並不存在。每個進程都有自己獨立的虛擬空間,每個進程只能訪問自己的地址空間,從而有效地隔離了進程。
起初,人們使用壹種叫做分段的方法。基本思想是將壹個虛擬空間映射到壹個地址空間,這個虛擬空間的大小是程序所需要的內存空間的大小。比如程序A需要10 MB的內存,那麽我們假設存在壹個地址從0x00A000000到100 MB的0x000000的虛空間,也就是虛擬空間,然後我們從實際物理內存中分配壹個大小相同的物理地址,假設物理地址從0x0010000開始,到0x00000結束。然後我們將這兩個大小相同的地址空間壹壹映射,即虛擬空間中的每個字節對應物理空間中的每個字節。這個映射過程是由軟件設置的,比如操作系統設置這個映射函數,實際的地址翻譯是由硬件完成的。
分段的方法基本上解決了上面提到的三個問題中的第壹個和第三個。首先,它實現了地址隔離,因為程序A和程序B被映射到兩個不同的物理空間區域,但是這種分段的方法仍然沒有解決我們的第二個問題,也就是內存利用效率的問題。段到內存區域的映射仍然是基於程序的。如果內存不足,整個程序就會換入換出到磁盤,必然會導致大量的磁盤訪問操作,從而嚴重影響速度。這種方法還是比較粗糙,粒度較大。實際上,根據程序局部性原理,壹個程序在運行時,只是在某壹段時間內頻繁使用壹小部分數據,也就是說,程序的大量數據在某壹段時間內是不會被使用的。人們自然會想到粒度更小的內存分段映射方法,這種方法充分利用了程序的局部性原理,大大提高了內存的利用率。這個方法就是分頁。
分頁的基本方法是人為地將地址空間劃分成固定大小的頁面,每個頁面的大小由硬件決定,或者硬件支持多種大小的頁面,頁面的大小由操作系統決定。例如,英特爾奔騰系列處理器支持4KB或4MB的頁面大小,因此操作系統可以選擇4KB或4MB的頁面大小,但同壹時間只能選擇壹種大小,因此整個系統的頁面大小是固定的。目前PC上幾乎所有的操作系統都使用4KB頁面。我們用的PC是32位虛擬地址空間,也就是4GB,所以如果把每頁分成4KB頁,就有1 048 576頁。物理空間也是這樣劃分的。
在這壹章中,我們回顧了整個計算機的基本硬件和軟件結構,包括CPU和外圍部件之間的連接。
模式,SMP和多核,軟硬件的分層架構,如何充分利用與系統軟件非常相關的CPU和設備驅動。
動畫、操作系統、虛擬空間、物理空間和頁面映射的基本概念。