1. 程式人生 > 實用技巧 >CPU工作原理和MMU初探

CPU工作原理和MMU初探

具體相關內容主要參考自一篇部落格,當然有結合其它內容,感謝博主提供的資源,這裡附上參考連結,http://www.cnblogs.com/xiangtao/archive/2013/04/11/3014815.html

關於CPU和MMU需要做幾點說明。

一、CPU

1、CPU核心功能單元

1)暫存器(register)

CPU內部的高速儲存器,常見暫存器(eax,esp,eip等),有些暫存器只能用於某種特定的用途,比如eip用作程式計數器,這稱為特殊暫存器(Special-purpose Register),而另外一些暫存器可以用在各種運算和讀寫記憶體的指令中,比如eax暫存器,這稱為通用暫存器(General-purpose Register)。

具體見下圖:

這些暫存器也被稱為整數暫存器(Integer register),具體見http://blog.csdn.net/cutemmll/article/details/7171448

2)程式計數器(PC)

一種特殊暫存器,儲存著CPU取下一條指令的地址,CPU按程式計數器儲存的地址去記憶體中取指令然後解釋執行,這時程式計數器儲存的地址會自動加上該指令的長度,指向記憶體中的下一條指令。

注意的是,EIP暫存器,用來儲存CPU要讀取指令的地址,CPU通過EIP暫存器讀取即將要執行的指令。每次CPU執行完相應的彙編指令之後,EIP暫存器的值就會增加。CPU每次執行控制器讀取完,相應的就再通過EIP暫存器去進行下一次的讀取指令工作。每次CPU讀取指令到指令緩衝區,相應的EIP暫存器的值增加,增加大小的就是讀取指令的位元組大小。如果執行完JMP指令,則EIP值會直接變成後面要跳轉的地址。

關於EIP,具體參考http://blog.csdn.net/xzhang76/article/details/8158749

3)指令譯碼器

4)算數邏輯單元

如果譯碼器將一條指令解釋為運算指令,就調動算術邏輯單元去做運算,比如加減乘除、位運算、邏輯運算。指令中會指示運算結果儲存到哪裡,可能儲存到暫存器中,也可能儲存到記憶體中。

5)地址和資料匯流排

CPU和記憶體之間用地址匯流排、資料匯流排和控制線連線起來,每條線上有1和0兩種狀態。如果在執行指令過程中需要訪問記憶體,比如從記憶體讀一個數到暫存器,執行過程可以想像成這樣:

1.CPU內部將暫存器對接到資料匯流排上,使暫存器的每一位對接到一條資料線,等待接收資料。

2.CPU通過控制線發一個讀請求,並且將記憶體地址通過地址線發給記憶體。
3.記憶體收到地址和讀請求之後,將相應的記憶體單元對接到資料匯流排的另一端,這樣,記憶體單元每一位的1或0狀態通過一條資料線到達CPU暫存器中相應的位,就完成了資料傳送。

2、CPU訪問裝置

CPU執行指令除了訪問記憶體之外還要訪問很多裝置(Device)。連線示意圖如下:

還有一些裝置整合在處理器晶片中。在上圖中,從CPU核引出的地址和資料匯流排有一端經總 線介面引出到晶片引腳上了,還有一端沒有引出,而是接到晶片內部整合的裝置上,無論是在CPU外部接匯流排的裝置還是在CPU內部接匯流排的裝置都有各自的地 址範圍,都可以像訪問記憶體一樣訪問,很多體系結構(比如ARM)採用這種方式操作裝置,稱為記憶體對映I/O(Memory-mapped I/O)。但是x86比較特殊,x86對於裝置有獨立的埠地址空間,CPU核需要引出額外的地址線來連線片內裝置(和訪問記憶體所用的地址線不同),訪問 裝置暫存器時用特殊的in/out指令,而不是和訪問記憶體用同樣的指令,這種方式稱為埠I/O(Port I/O)。

從 CPU的角度來看,訪問裝置只有記憶體對映I/O和埠I/O兩種,要麼像記憶體一樣訪問,要麼用一種專用的指令訪問。其實訪問裝置是相當複雜的,計算機的設 備五花八門,各種裝置的效能要求都不一樣,有的要求頻寬大,有的要求響應快,有的要求熱插拔,於是出現了各種適應不同要求的裝置匯流排,比如PCI、 AGP、USB、1394、SATA等等,這些裝置匯流排並不直接和CPU相連,CPU通過記憶體對映I/O或埠I/O訪問相應的匯流排控制器,通過匯流排控制 器再去訪問掛在總線上的裝置。所以上圖中標有“裝置”的框可能是實際的裝置,也可能是裝置匯流排的控制器。

訪問裝置還有一點和訪問記憶體不同。記憶體只是儲存資料而不會產生新的資料,如果CPU不去讀它,它也不需要主動提供資料給CPU,所以記憶體總是被動地等待被讀 或者被寫。而裝置往往會自己產生資料,並且需要主動通知CPU來讀這些資料,例如敲鍵盤產生一個輸入字元,使用者希望計算機馬上響應自己的輸入,這就要求鍵 盤裝置主動通知CPU來讀這個字元並做相應處理,給使用者響應。這是由中斷(Interrupt)機 制實現的,每個裝置都有一條中斷線,通過中斷控制器連線到CPU,當裝置需要主動通知CPU時就引發一箇中斷訊號,CPU正在執行的指令將被打斷,程式計 數器會指向某個固定的地址(這個地址由體系結構定義),於是CPU從這個地址開始取指令(或者說跳轉到這個地址),執行中斷服務程式 (ISR,Interrupt Service Routine), 完成中斷處理之後再返回先前被打斷的地方執行後續指令。比如某種體系結構規定發生中斷時跳轉到地址0x00000010執行,那麼就要事先把一段ISR程 序載入到這個地址,ISR程式是核心程式碼的一部分,在這段程式碼中首先判斷是哪個裝置引發了中斷,然後呼叫該裝置的中斷處理函式做進一步處理。

由於各種裝置的操作方法各不相同,每種裝置都需要專門的裝置驅動程式(Device Driver),一個作業系統為了支援廣泛的裝置就需要有大量的裝置驅動程式,事實上Linux核心原始碼中絕大部分是裝置驅動程式。裝置驅動程式通常是核心裡的一組函式,通過讀寫裝置暫存器實現對裝置的初始化、讀、寫等操作,有些裝置還要提供一箇中斷處理函式供ISR呼叫。

二、MMU

現代作業系統普遍採用虛擬記憶體管理(Virtual Memory Management)機制,這需要處理器中的MMU(Memory Management Unit,記憶體管理單元)提供支援。這樣就涉及到虛擬記憶體和實體記憶體的概念。

1)MMU功能

MMU主要用來做地址轉換,事實上,過程是CPU每次執行訪問記憶體的指令都會自動引發MMU做查表和地址轉換操作,地址轉換操作由硬體自動完成,不需要用指令控制MMU去做。

MMU除了做記憶體地址轉換外,還提供記憶體保護的功能。現代作業系統通常把虛擬記憶體地址空間劃分為使用者地址空間和核心地址空間,例如x86平臺的Linux系統虛擬地址空間是 0x00000000~0xffffffff,前3GB(0x00000000~0xbfffffff)是使用者空間,後 1GB(0xc0000000~0xffffffff)是核心空間。

2)記憶體保護過程

當CPU要訪問一個VA時,MMU會檢查CPU當前處於使用者模式還是特權模式,訪 問記憶體的目的是讀資料、寫資料還是取指令,如果和作業系統設定的頁面許可權相符,就允許訪問,把它轉換成PA,否則不允許訪問,產生一個異常 (Exception)。異常的處理過程和中斷類似,不同的是中斷由外部裝置產生而異常由CPU內部產生,中斷產生的原因和CPU當前執行的指令無關,而異常的產生就是由於CPU當前執行的指令出了問題,例如訪問記憶體的指令被MMU檢查出許可權錯誤,除法指令的除數為0等都會產生異常。

CPU在產生中斷或異常時不僅會 跳轉到中斷或異常服務程式,還會自動切換模式,從使用者模式切換到特權模式,因此從中斷或異常服務程式可以跳轉到核心程式碼中執行。事實上,整個核心就是由各 種中斷和異常處理程式組成的。總結一下:在正常情況下處理器在使用者模式執行使用者程式,在中斷或異常情況下處理器切換到特權模式執行核心程式,處理完中斷或 異常之後再返回使用者模式繼續執行使用者程式。

段錯誤我們已經遇到過很多次了,它是這樣產生的:
1.使用者程式要訪問的一個VA,經MMU檢查無權訪問。
2.MMU產生一個異常,CPU從使用者模式切換到特權模式,跳轉到核心程式碼中執行異常服務程式。
3.核心把這個異常解釋為段錯誤,把引發異常的程序終止掉。