Java架構師成長之道之計算機組成原理組成篇
2.1 計算機總線
2.1.1 總線概述
以通用串行總線USB(Universial Serial Bus)為例子來理解什么是總線,
首先它提供了對外的連接接口,不同的設備(鼠標、鍵盤、U盤、移動硬盤)通過這個接口都可以進行連接,USB也成為了連接標准,促使外圍設備接口的統一。除此以外還有PCI總線,Thunderbolt總線等等,總線是為了解決不同設備之間的通訊問題。
2.1.2 總線分類
總線分為片內總線和系統總線兩類。
- 片內總線
片內總線是芯片內部的總線,以CPU為例,總線連接高速緩存,控制器,中斷系統,運算器。
片內總線可以連接寄存器與寄存器,寄存器與控制器、運算器之間的設備。
片內總線就是高集成度芯片內部的信息傳輸線,用來簡化芯片結構。 - 系統總線
系統總線用於連接計算機外圍設備,可以分為如下三類:- 數據總線
數據總線位數和CPU的位數相同(32位,64位 ),用於雙向傳輸各個部件的數據信息。 - 地址總線
如果地址總線位數為n,那么尋址的范圍是0-2n次方,地址總線的位數和存儲單元有關 - 控制總線
控制總線主要是用於發出各種控制信號的傳輸線,控制信號經過控制總線從一個組件發給另外一個組件,控制總線可以監事不同組件的狀態(就緒/未就緒)
- 數據總線
2.1.3 總線仲裁
總線仲裁主要是解決了不同組件使用總線的優先級。
常用的總線總裁的方法有如下三種:
- 鏈式查詢
設備之間通過電路串聯,電路復雜低,仲裁方式簡單,但是優先級低的設備難以獲取總線的使用權,設備的優先級就體現在鏈式查詢的先后順序。 - 計時器定時查詢
仲裁控制器對設備進行編號並使用計數器累計計數,接到仲裁信號以后,往所有設備發出計數值。計數值與設備編號一致則獲得總線使用權。 - 獨立請求
每個設備均有總線獨立連接仲裁控制器,設備可單獨向仲裁器發送請求和接受請求,當同時收到多個信號,仲裁器有權按照優先級分配使用權。
2.2 計算機的輸入輸出設備
2.2.1 常見的輸入輸出設備
常見的輸入設備分為字符輸入設備和圖像輸入設備。
-
字符輸入設備
最常見的字符輸入設備是鍵盤,鍵盤可以分為薄膜鍵盤、機械鍵盤按照不同的段落感、聲音、壓力和鍵程序分為黑軸、紅軸、青軸、茶軸四種和電容鍵盤。 -
圖形輸入設備
最常見的圖形輸入設備有鼠標、掃描儀。 -
圖像輸出設備
最常見的圖形輸出設備有液晶顯示器,打印機以及投影儀。
2.2.2 輸入輸出接口的通用設計
輸入輸出接口的通用設計主要有以下幾點
-
數據線:是IO設備與主機之間的信息交換傳輸線,按照用途不同分為單向傳輸線和雙向傳輸線。
-
狀態線:IO設備狀態向主機報告的信號線,主機可以通過狀態線查詢設備是否已經正常連接並就緒,同時還可以查詢是否已經被別的設備占用。
-
命令線: CPU向設備發送命令的信號線,例如讀寫信號、啟動、停止信號。
-
設備選擇線:主機選擇與IO設備進行操作的信號線,對連接在總線上的設備進行選擇。
2.2.3 CPU與IO設備的通訊方法
CPU與IO設備的通訊方法主要有程序中斷的方法以及DMA(直接存儲器訪問)兩種
- 程序中斷
當外圍IO設備准備就緒,向CPU發出中斷信號,CPU有專門的電路響應中斷信號,當CPU收到中斷信號,就會暫停當前的任務,轉而處理IO設備的工作,當處理完成后再處理當前的任務。
程序中斷提供低速設備通知CPU的一種異步方式,CPU可以高速運算的同時兼顧低速設備的響應,但是CPU速度與IO設備速度不匹配,所以會降低CPU的效率。
- DMA(直接存儲訪問)
DMA直接連接主存和IO設備,DMA工作時不需要CPU的參與。
當主存與IO設備交換信息時,不需要中斷CPU,可以大大提高CPU效率。
在硬盤、顯卡中都有DMA的存在。
2.3 計算機的存儲器
2.3.1存儲器的分類
存儲器的分類按照存儲介質可以分為半導體存儲器和磁存儲器
常見的半導體存儲器有內存、固態硬盤。
常見的磁存儲器有磁盤。
存儲器按照存取方式分類可以分為如下三種:
隨機存儲器(RAM),可以隨機讀寫,存儲的時間和位置沒有關系。
串行存儲器,存儲的時間和位置有關系,
只讀存儲器(ROM),只讀不寫,例如手機的固件,電腦的BIOS。
2.3.2 存儲器的層次結構
在選配磁盤時考慮的通常是讀寫速度以及磁盤的容量和價格三大因素,而存儲器的層次結構可以分為緩存、主存和輔存。
緩存是CPU的寄存器和高速緩存,容量最低,速度最快,價格最高
主存就是計算機的內存,容量適中,速度適中,價格適中
輔存就是計算機的外部存儲設備,例如磁盤、移動硬盤等。 容量最高,速度最慢,價格低
在計算機存儲結構中,CPU可以和高速緩存、主存直接進行通訊,高速緩存和主存可以直接進行通訊,這種層次結構被稱為緩存-主存層次,其實現方式就是在CPU和主存之間加一層速度快但是容量小的高速緩存, 用於解決CPU和主存速度不匹配的問題。
其實現原理就是局部原理:CPU訪問存儲器時,無論是存取指令還是存取數據,所訪問的存儲單元都趨於聚集在一個較小的連續區域中,CPU將程序經常訪問的內存數據加載到緩存中,然后直接訪問緩存即可。
主存和輔存直接進行通訊,這種層次被稱為主存-輔存層次,其實現就是在主存之外增加輔助存儲器,其目的是解決主存容量不足的問題。
2.3.3 計算機的主存儲器和輔助存儲器
計算機的主存儲器也被稱為隨機存儲器(Random Access Memory)即內存,RAM通過電容存儲數據,必須每隔一段時間刷新一次,如果掉電,那么一段時間后將丟失所有數據。
內存由半導體存儲體、驅動器、譯碼器、讀寫電路和控制電路組成。
CPU通過內部的主存數據寄存器(mdr)通過數據總線訪問讀寫電路,同時CPU的主存地址寄存器(MAR)通過地址總線指定數據的位置,然后通過數據總線傳輸數據。
不同的操作系統對內存的支持是不一樣的,目前最常用的操作系統分為32位和64位。
32位系統最大支持4GB內存。因此32位系統的地址總線只有32位數
而64位系統支持超過4GB的內存,例如筆記本的8GB-64GB,服務器通常是16GB-256GB。
目前計算機中常用的輔助存儲器有磁盤、移動硬盤。
2.4 計算機的高速緩存
2.4.1 高速緩存的工作原理
計算機的高速緩存位於CPU和主存之間,其出現的目的是為了解決CPU與主存速度不匹配,提高CPU效率。
為了了解高速緩存的工作原理,首先需要了解主存的相關概念:字和字塊
字:存放在一個存儲單元的二進制代碼組合,一個字可以表示數據、指令或者字符串
字塊:存儲在連續的存儲單元中而被看做一個單元的一組字,即字塊包含了多個字。
假設一個字有32bits,一個字塊共有B個字,主存共有M個字塊。
那么主存總字數=BM,而主存總容量=BM*32bits
而字的地址包含兩個部分,前m位表示字塊在內存中的地址,后b位指定字在當前字塊的地址。因此2m=M(總字塊),2b=B(總字數)。
假設主存的用戶空間為4G,字塊大小為4M,字長位32位,則對於字地址中的塊地址m和塊內地址b的位數,至少應該是多少?
首先求出字塊數:4G/4M=4*1024M/4=1024
字塊地址m: log2(1024)=10
log2(1024)屬於對數運算,其計算結果可以使用Windows10自帶的計算器獲取,
首先切換至科學型,默認是標准型,然后分別輸入1024、log、/、2、log、=即可以求出結果
塊內字數:4M/32bit=1048576
塊內地址:log2(1048576)=20
log2(1048576)也是屬於對數運算,其計算結果可以使用Windows10自帶的計算器實現獲取,
首先切換至科學型,默認是標准型,然后輸入1048576、log、/、2、log、=即可以求出結果
根據計算結果m≥10,b≥20得知字地址的塊地址至少是10位,字地址的塊內地址至少是20位。
高速緩存和主存的存儲邏輯結構類似,緩存相對於主存容量較小,速度更快等特點。
CPU訪問高速緩存的兩種情況
- CPU需要的數據在緩存中
- CPU需要的數據不在緩存中需要從主存中拿,然后復制到高速緩存中
命中率和訪問效率是衡量緩存的重要性能指標
理論上CPU每次都能從高速緩存中獲取數據的時候,命中率為1,但是由於高速緩存的容量遠遠小於主存的容量,因此命中率不可能為1。
命中率(h)計算的公式: 訪問高速緩存的次數占總次數的比例
訪問主存的次數:Nm
訪問Cache的次數Nc
h=Nc/(Nc+Nm)
訪問效率:e
訪問主存的時間:tm
訪問緩存的時間為tc
訪問Cahe-主存 系統平均時間:ta=h*tc+(1-h)*tm
e=tc/ta=tc/h*tc+(1-h)*tm
緩存的命中率和訪問效率例子:
假設CPU在執行某段程序時,共訪問了Cache命中2000次,訪問主存50次,已知Cache的存取時間為50ns,主存的存取時間為200ns,求Cache-主存系統的命中率、訪問效率以及平均訪問時間。
命中率計算公式:
h=Nc/(Nc+Nm)
h=2000/(2000+50)≈0.97 即緩存的命中率為97%
訪問效率計算公式:
e=tc/ta=tc/htc+(1-h)tm
e=tc/ta=tc/htc+(1-h)tm=50/(0.97*50+(1-0.97)200)=50/(48.5+0.03200)=50/54.5≈0.917
CPU訪問存儲系統的平均訪問時間
ta=0.97*50+(1-0.97)200)=48.5+0.03200=54.5ns
2.4.2 高速緩存的替換策略
在CPU執行程序時,為了提高執行效率,應該盡量從高速緩存中獲取數據,也就是提高緩存的命中率和訪問效率,此時需要良好的替換策略,高速緩存的替換時機是CPU需要的數據不在高速緩存中,此時需要從主存中獲取數據,此時按照相關的策略替換高速緩存的數據,常用的高速緩存替換策略有如下幾種策略。
- 隨機算法
隨機算法是每次需要替換緩存中的數據時隨機選取高速緩存的數據替換掉。 - 先進先出算法(FIFO)
先進先出算法把高速緩存看做一個先進先出的隊列,如果需要替換高速緩存的數據,優先替換最先進入隊列的字塊。
假設緩存一共可以緩存1-8一共8個字塊,CPU運行程序時某次任務觸發了緩存替換,需要將第9個字塊存儲到高速緩存中,此時根據FIFO的特性,第一個字塊的數據將會從高速緩存中移除,然后將第九個字塊放到高速緩存中。
-
最不經常使用法(LFU)
LFU優先淘汰掉最不經常使用的字塊,因此需要額外的空間記錄字快的使用頻率,假設在某個時刻觸發替換的行為,此時會將命中頻率最低的字塊替換掉。 -
最近最少使用算法(LRU)
LRU優先淘汰一段時間內沒有使用的字塊,有多種實現方法,通常使用雙向鏈表實現,把當前訪問的字塊節點至於鏈表的前面,保證鏈表頭部的字塊是最近使用的,當需要淘汰的時候將鏈表尾部的字塊淘汰掉。
2.5 計算機的指令系統
2.5.1 機器指令的形式
機器指令由操作碼和地址碼兩部分組成。
其中操作碼指明了指令所要完成的操作,操作碼的位數反映了機器的操作種類,例如操作碼有8位,即有2^8=256種操作。
地址碼是給出操作數或者操作數的地址,因為機器指令本質上是操作數據,CPU根據數據或者數據的地址進行相應的運算,地址碼分為三地址指令、二地址指令和一地址指令。
三地址指令的機器指令包含操作碼(OP),地址1(addr1),地址2(addr2),地址3(addr3),三地址指令通常會完成(addr1)OP(addr2)->(addr3),以操作碼為加法為例子,將add1和add2對應的值相加,然后將相加的結果存放在addr3中。
二地址指令的機器指令包含操作碼(OP),地址1(addr1)和地址2(addr2),二地址指令通常會完成(addr1)OP(addr2)-->(addr1)或者->(addr2),即將addr1和addr2按照操作碼進行相關的運算后將結果存儲在addr1或者addr2中,二地址指令則可以理解為類似a=a+b這樣的操作。不過這個只是從較為宏觀的角度去理解指令了。在計算機內部,a=a+b可能會分成多個指令去執行,比如:先將變量從內存加載到通用數據寄存器,然后從通用數據寄存器移動到ALU的緩沖寄存器,然后再做運算,而這里的數據移動也可以理解為二地址指令(源地址->目的地址)。
一地址指令的機器指令(addr1)OP->(addr1)或者(addr1)OP(ACC)->(addr1),一地址指令最常用的操作就是自增運算,只有一個操作數。
除了有地址指令之外還有一種零地址指令,即在機器指令中無地址碼,例如空操作、停機操作和中斷返回操作等等。
2.5.2 機器指令的操作類型
機器指令的操作類型主要有數據傳輸類型,算術邏輯操作類型,控制指令類型三種。
-
數據傳輸包含寄存器之間、寄存器與存儲單元以及存儲單元(高速緩存、主存、輔存)之間傳輸,而數據讀寫、交換地址數據、清零、置一等操作都是數據傳輸類型。
-
算術邏輯操作包含 操作數之間的加減乘除運算,與或非等邏輯運算以及移位運算(左移(乘以2),右移(除2)操作。
-
控制指令包含等待指令、停機指令、空操作指令、中斷指令等等。
2.5.3 機器指令的尋址方式
機器指令的尋址方式包含指令尋址和數據尋址兩種方式
指令尋址包含順序尋址和跳躍尋址
順序尋址就是按照指令的順序依次執行,而當遇到跳轉指令時需要跳轉尋址。
數據尋址主要有立即尋址、直接尋址和間接尋址三種方式。
-
立即尋址:指令可以直接包含操作數,即無需要訪問存儲器,直接從指令獲取操作數 例如指令 OP addr1 6,優點是速度非常快,但是地址碼位數限制操作數的表示范圍。
-
直接尋址:機器指令直接給出操作數在主存的地址,直接尋址尋找操作數簡單,無需計算數據的地址,優點是速度較快,缺點是地址碼的位數限制操作數的表示范圍。
-
間接尋址:指令地址碼給出的是操作數地址的地址,例如指令 R1(OP)(add2),add2是主存操作數地址的地址,因此需要訪問一次或者多次主存來獲取操作數。優點是操作數的尋址范圍大,缺點是速度慢。
2.6 計算機的CPU
2.6.1 計算機的控制器
計算器控制器的作用是協調和控制計算機運行,計算機控制器包含如下幾部分組成
-
程序計數器
程序計數器主要是用來存儲下一條指令的地址,當程序運行時,CPU循環從程序計數器中獲取指令,當指令被拿出時,程序計數器會指向下一條指令,程序計數器是提供給其他控制單元當前需要執行指令的地址。 -
時序發生器
時序發生器屬於電器工程領域,用於發送時序脈沖,CPU依據不同的時序脈沖有節奏的進行工作。生活中學習各種樂器根據節拍器學習,而時序發生器就是類似於樂器的節拍器。 -
指令譯碼器
計算機指令由操作碼和地址碼組成,指令譯碼器會翻譯操作碼對應的操作以及控制傳輸地址碼對應的數據。 -
寄存器
- 指令寄存器
指令寄存器主要用於從主存或者高速緩存存儲計算機指令,當CPU需要執行相關指令時直接從指令寄存器中獲取指令並執行。 - 主存地址寄存器
主存地址寄存器保存當前CPU正要訪問的主存單元的地址,使用地址總線和主存進行通訊。 - 主存數據寄存器
主存數據寄存器保存當前CPU正要讀寫的主存數據,使用數據總線和主存進行通訊。 - 通用寄存器
用於暫時存放或傳送數據指令,還可以保存算術邏輯單元(ALU)運算的中間結果,通用寄存器的容量比一般專用的寄存器大。
- 指令寄存器
-
總線
用於控制器和其他組件通訊
2.6.2 計算機的運算器
計算機的運算器主要是用來進行數據的運算,由如下部分組成
-
數據緩沖器
數據緩沖器分為輸入緩沖和輸出緩沖,輸入緩沖暫時存放外部設備輸入的數據,輸出緩存暫時存放送往外部設備的數據 -
算術邏輯單元:(ALU)
ALU可以完成算術運算、邏輯運算、位運算,至於ALU是如何運算,請聽下回分解。 -
狀態字寄存器
狀態字寄存器用於存放運算的狀態,例如條件碼、進位、溢出、結果正負等等,同時可以存放運算的控制信息,例如調試程序時的調試跟蹤標記位以及允許中斷位等等。 -
通用寄存器
主要是用於暫時存放或傳送數據或指令,同時可以保存ALU運算的中間結果,容量比一般專用寄存器大。 -
總線
用於運算器和其他組件通訊
2.6.3 計算機指令的執行過程

計算機指令執行主要包含取指令、分析指令、執行指令三個步驟,這三個步驟由高速緩存(緩存數據和指令)、運算器、控制器完成,而CPU內部的高速緩存、運算器和控制器和由片內總線連接,為了演示指令執行的過程,首先將指令執行過程中使用的相關的設備和測試數據羅列出來。
-
高速緩存
- 數據緩存:緩存地址和數據信息
- 地址緩存:緩存地址、操作碼和地址碼信息
數據緩存測試數據
地址 | 數據 |
---|---|
1 | 188 |
2 | 199 |
3 | 110 |
4 | 120 |
地址緩存測試數據
地址 | 操作碼 | 地址碼 |
---|---|---|
101 | MOV | R0,R1 |
102 | LAD | R1,6 |
103 | ADD | R1,R2 |
104 | ADD | R1,R3 |
105 | JMP | 102 |
運算器
- 數據緩沖器
- 算術邏輯單元(ALU)
- 狀態字寄存器
- 通用寄存器
- R0(100)
- R1(10)
控制器
- 程序計數器
- 指令寄存器
- 指令譯碼器
- 時序發生器
這里以執行地址緩存測試數據為101的指令:將R0的值移動到R1中 為例,說明指令執行的過程
高速緩存緩存數據(數據、指令)->程序計數器存儲指令地址->指令緩存 根據指令地址獲取操作碼、地址碼->指令寄存器緩存操作碼、地址碼->指令譯碼器譯碼->程序計數器加1->運算器->寄存器->ALU->狀態字寄存器->數據緩沖器。
CPU在執行程序時,首先將內存中的機器指令的數據以及指令緩存在CPU的高速緩存中,然后從高速緩存中獲取指令執行。首先程序計數器將當前執行的指令地址為101緩存起來,但是程序計數器只知道指令的地址,而不知道指令具體的內容,程序計數器可以根據指令的地址通過總線訪問高速緩存的指令緩存來獲取指令地址為101的操作碼(MOV)和地址碼(RO,R1),再通過片內總線訪問指令寄存器,將指令的操作碼(MOV)和地址碼(R0,R1)緩存起來,因為指令寄存器不知道指令的具體內容,同時還需要將指令發送到指令譯碼器,發送指令之后程序計數器要加1,此時程序計數器存儲下一條執行的指令102,指令譯碼器拿到地址為101的指令負責譯碼(理解指令的具體內容:將R0寄存器的數據移動到R1寄存器中去)后發出控制信號,指令譯碼器通過片內總線進入運算器中,運算器獲取控制信號后將R0加載到ALU中去進行相關的運算,再把R0的數據通過數據總線傳輸到數據緩沖器,數據緩沖器將R0的值覆蓋到R1,此時R1的值就是100,此時高速緩存地址為101的指令完成。
-
取指令
CPU在執行程序時,首先將主存中的機器指令緩存在高速緩存中,然后從指令緩存中獲取指令,並將指令送到指令寄存器。 -
分析指令
首先從指令寄存器取出指令傳輸到指令譯碼器進行譯碼操作,識別區分不同的指令類別和各種操作數據的方法。然后指令譯碼器發出控制信號,同時程序計數器加1,指向下一條指令。 -
執行指令
首先裝載數據到寄存器,通過ALU處理數據,如果有進位、溢出會通過狀態字寄存器記錄運算狀態,最后將運算結果返回。
2.6.4 CPU流水線設計
在指令的執行過程中取指令和和分析指令是由控制器完成的,而執行指令主要是由運算器完成的,也就是運算器和控制器不能同時工作,這樣會導致CPU的綜合利用效率不高,因此我們需要改進指令執行的過程來提高CPU的效率。
CPU的流水線設計類似於工廠的裝配線,其特點是工廠的裝配線使得多個產品可以被加工,在同一個時刻,不同的產品位於不同的加工階段。
在未使用流水線設計之前,如果想要執行兩條指令的流程如下
取指令->分析指令->執行指令->取指令->分析指令->執行指令 串行執行的。
在使用流水線設計之后,如果想要執行多條指令的流程如下
指令 | 時間片 | 時間片 | 時間片 | 時間片 | 時間片 | 時間片 | 時間片 | 時間片 | 時間片 |
---|---|---|---|---|---|---|---|---|---|
1 | 取指令 | 分析指令 | 執行指令 | ||||||
2 | 取指令 | 分析指令 | 執行指令 | ||||||
3 | 取指令 | 分析指令 | 執行指令 | ||||||
4 | 取指令 | 分析指令 | 執行指令 | ||||||
5 | 取指令 | 分析指令 | 執行指令 | ||||||
6 | 取指令 | 分析指令 | 執行指令 | ||||||
7 | 取指令 | 分析指令 |
由於每個時間片都有一條或者多條指令正在執行,CPU流水線設計的執行指令效率是串行執行效率的三倍左右,公式如下所示
串行執行m條指令: T1=3t*m
流水線執行m條指令: T2=t*(M+2)
效率計算方式如下所示:
H=T2/T1=t*(m+2)/3tm=1/3+1/(3m)