【软件开发底层知识修炼】三 深入浅出处理器之三 内存管理与内存管理单元(MMU)
學習交流加
- 個人qq:
1126137994 - 個人微信:
liu1126137994 - 學習交流資源分享qq群:
962535112
上一篇文章學習了中斷的概念與意義,以及中斷的應用-斷點調試原理。點擊鏈接復習上一篇文章:中斷的概念與意義
本片文章繼續學習處理器相關的知識-內存管理。包括:內存管理單元MMU的作用,虛擬內存與物理內存之間的映射方式,頁表的概念,高速緩存(Cache)的作用,物理內存與高速緩存之間的映射關系等。當然,想要深入了解,本文并不適合,本文只是從原理上,講述以上幾者之間的關系。
文章目錄
- 1、內存管理單元MMU
- 1.1、虛擬內存
- 1.2、 頁式內存管理
- 1.21 頁的概念
- 1.22 頁表的概念
- 1.23 頁命中
- 1.24 缺頁
- 1.25 分配頁面
- 1.26 程序的局部性原則
- 1.3 虛擬內存作為內存管理工具
- 1.4、虛擬內存作為內存保護工具
- 2、地址翻譯
- 3、總結
1、內存管理單元MMU
這里假設大家了解虛擬內存的由來。參考《深入理解計算機系統》講虛擬內存的章節
實際上我們寫的程序,都是面向虛擬內存的。我們在程序中寫的變量的地址,實際上是虛擬內存中的地址,當CPU想要訪問該地址的時候,內存管理單元MMU會將該虛擬地址翻譯成真實的物理地址,然后CPU就去真實的物理地址處取得數據。
這里說的虛擬地址,是指虛擬地址空間中地址。這里我們說的虛擬地址空間,實際上是在磁盤上的一塊空間(常見的是4G的進程虛擬地址空間)。具體這4G的虛擬地址空間的來龍去脈,參考《深入理解計算機系統》第九章。
MMU:內存管理單元。它是一個硬件,不是軟件。它用于將虛擬地址翻譯成實際的物理內存地址。同時它還可以將特定的內存塊設置成不同的讀寫屬性,進而實現內存保護。注意,MMU是硬件管理,不是軟件實現內存管理。
總結來說,MMU能實現以下功能:
- 虛擬內存。有了虛擬內存,可以在處理器上運行比實際物理內存大的應用程序。為了使用虛擬內存,操作系統通常要設置一個交換區(通常在硬盤上),通過將內存中不活躍的數據與指令放到交換區,以騰出物理內存來為其他程序服務。
- 內存保護。通過這一功能,可以將特定的內存塊設置為讀、寫或者可執行的屬性。比如將不可變的數據或者代碼設為只讀的,這樣可以防止被惡意串改。
1.1、虛擬內存
進程的概念大家都知道。
每一個進程都獨立的運行在自己的虛擬地址空間。為了理解這一個概念。我們可以看一個而簡單的例子:
看一下下面的代碼:
main.c
如果我同時運行該程序兩次。打印結果會是一樣么?答案是結果肯定一樣,運行結果都為:
當然,這是在我的計算機上,在你的計算機上g_int地址可能不一樣,但是同時運行該程序兩次,結果肯定是一樣的。其實這個答案很多人都知道是一樣的,初學者都知道。但是初學者說不清楚是為什么。
- 分析
這個進程運行兩份實例的時候。在物理內存中,實際上是以下分布情況:
進程1和進程2 位于不同的地址。但是我們程序打印的g_int全局變量的地址值,是一樣的。
這里就引入了虛擬內存的概念。我們寫程序,面向的是虛擬地址空間。寫的程序的內容,都可以看成是在虛擬地址空間中運行(實際上最終是將虛擬地址空間映射到了物理地址空間)。如下圖:
以上只是簡圖。
我們可以看到。main.o可執行程序,運行兩份實例時,相當于兩個進程。這兩個進程都有自己獨立的虛擬地址空間。然后將虛擬地址空間里的代碼數據映射到內存中,從而被CPU執行與處理。在物理內存中,g_int這個全局變量的物理地址確實不同。但是在虛擬內存中,由于進程1與進程2的虛擬地址空間完全一樣(同一個可執行程序代碼),那么g_int地址,實際上就是一樣的。
CPU在執行指令與數據時,獲得的是虛擬內存的地址。但是CPU只能去物理內存尋址。此時,MMU就派上用場了。MMU負責,將虛擬地址,翻譯成,真正運行時的物理地址。
MMU是如何將虛擬地址翻譯成物理地址的,這個后面講。現在先要了解一下交換區的概念。
- 交換區: 實際上就是一塊磁盤空間(硬盤空間)。虛擬內存與物理內存映射的時候,是將虛擬內存的代碼放到交換區中,以后在CPU想要執行相關的指令或者數據時,如果內存中沒有,先去交換區將需要的指令與數據映射到物理內存,然后CPU再執行。
虛擬內存與交換取的這種概念,實現了大內存需求量的(多個)進程,能夠(同時)運行在較小的物理內存中。如下圖所示:
上圖中,說的是進程的局部代碼在物理內存中運行。是因為程序具有局部性原則,所以在某一段很小的時間段內,只有很少一部分代碼會被CPU執行。具體可以參考下一篇文章。
到這里,我們應該大致明白了虛擬內存的作用與簡單機制。還剩下MMU如何翻譯虛擬地址為物理地址的,這放到最后講解。現在先總結一下虛擬內存機制:
- 虛擬內存需要重新映射到物理內存
- 虛擬地址映射到物理地址中的實際地址
- 每次只有進程的少部分代碼會在物理內存中運行
- 大部分代碼依然位于磁盤中(存儲器硬盤)
1.2、 頁式內存管理
上一節籠統的介紹了虛擬內存的概念。接下來學習內存管理中的一種方式:頁式內存管理。
頁式內存管理中我們需要了解:
- 頁的概念
- 頁表的概念
- 缺頁的概念與頁命中的概念
- 分配頁面
- 程序的局部性原則
1.21 頁的概念
由1.1的內容,我們知道了交換區。我們知道交換區里面存放的是大部分的可執行代碼與數據。而物理內存中,執行的是少部分的可執行代碼與數據。那么當物理內存中的代碼與數據執行完需要執行接下來的代碼,而剛好接下來的代碼還在交換區中沒有映射到物理內存(這稱為缺頁,后面會講),那么此時就需要從交換區獲取程序的代碼,將它拿到物理內存執行。那么一次拿多少代碼過來呢?這是一個問題!
為了CPU的高效執行以及方便的內存管理(詳細原因見以后的文章),每次需要拿一個頁的代碼。這個頁,指的是一段連續的存儲空間(常見的是4Kb),也叫作塊。假設頁的大小為P。在虛擬內存中,叫做虛擬頁(VP)。從虛擬內存拿了一個頁的代碼要放到物理內存,那么自然物理內存也得有一個剛好一般大小的頁才能存放虛擬頁的代碼。物理內存中的頁叫做物理頁(PP)
在任何時刻,虛擬頁都是以下三種狀態中的一種:
- 未分配的:VM系統還未分配的頁(或者未創建)。未分配的頁還沒有任何數據與代碼與他們相關聯,因此也就不占用任何磁盤。
- 緩存的: 當前已緩存在物理內存中的已分配頁
- 未緩存的:未緩存在物理內存中的已分配頁
下圖展示了一個8個虛擬頁的小虛擬內存。其中:虛擬頁0和3還沒有被分配,因此在磁盤上還不存在。虛擬頁1、4、 6被緩存在物理內存中。虛擬頁2、 5、 7已經被分配,但是還沒有緩存到物理內存中去執行。
1.22 頁表的概念
1.21節用到了緩存這個詞。這里假設大家都理解緩存的概念。
虛擬內存中的一些虛擬頁是緩存在物理內存中被執行的。理所應當,應該有一種機制,來判斷虛擬頁,是否被緩存在了物理內存中的某個物理頁上。如果不命中(需要一個頁的代碼,但是這個頁未緩存在物理內存中),系統還必須知道這個虛擬頁存放在磁盤上的哪個位置,從而在物理內存中選擇一個空閑頁或者替換一個犧牲頁,并將需要的虛擬頁從磁盤復制到物理內存中。
這些功能,是由軟硬件結合完成的。 包括操作系統軟件,MMU中的地址翻譯硬件,和一個存放在物理內存中的頁表的數據結構。
上一節說將虛擬頁映射到物理頁,實際上就是MMU地址翻譯硬件將一個虛擬地址翻譯成物理地址時,都會去讀取頁表的內容。操作系統負責維護頁表的內容,以及在磁盤與物理內存之間來回傳送頁。
下圖是一個頁表的基本組織結構(實際上不止那些內容):
如上圖所示:
頁表實際上就是一個數組。這個數組存放的是一個稱為頁表條目(PTE)的結構。虛擬地址空間的每一個頁在頁表中,都有一個對應的頁表條目(PTE)。虛擬頁地址(首地址)翻譯的時候就是查詢的各個虛擬頁在頁表中的PTE,從而進行地址翻譯的。
現在假設每一個PTE都有一個有效位和一個n位字段的地址。其中
- 有效位:表示對應的虛擬頁是否緩存在了物理內存中。0表示未緩存。1表示已緩存。
- n位地址字段:如果未緩存(有效字段為0),n位地址字段不為空的話,這個n位地址字段就表示該虛擬頁在磁盤上的起始的位置。如果這個n位字段為空,那么就說明該虛擬頁未分配。如果已緩存(有效字段為1),n位地址字段肯定不為空,它表示該虛擬頁在物理內存中的起始地址。
綜上分析,就得知,上圖中:四個虛擬頁VP1 , VP2, VP4 , VP7 是被緩存在物理內存中。 兩個虛擬頁VP0, VP5還未被分配。但是剩下的虛擬頁VP3 ,VP6已經被分配了,但是還沒有緩存到物理內存中去執行。
注意:任意的物理頁,都可以緩存任意的虛擬頁。(因為物理內存是全相聯的)
1.23 頁命中
考慮下圖的情形:
假設現在CPU想讀取VP2頁面中的某一個字節的內容。會發生什么呢?
當CPU得到一個地址vaddr想要訪問它(這個addr就是上面想要訪問的某一個字節的地址),通過后面會學習的MMU地址翻譯硬件,將虛擬地址addr作為索引定位到頁表的PTE條目中的PTE2(這里假設是PTE2),從內存中去讀到PTE2的有效位為1,說明該虛擬頁面已經被緩存了,所以CPU使用該PTE2條目中的物理內存地址(這個物理內存地址是PP1中的起始地址)構造出vaddr的物理地址paddr(這個地址是PP1頁面起始地址或后面的某一個地址)。然后CPU就會去paddr這個物理內存地址去取數據。這種情況,就是也命中。
實際上,上面的VP2的起始地址與paddr地址,很類似于內存的分段機制(X86以前就是分段機制),CPU訪問內存的地址是“段地址:偏移地址”或者叫做“CS:IP”。而我們現在學習的是分頁機制,他們都是一種內存管理機制。
1.24 缺頁
什么是缺頁?
考慮以下圖示情形:
當CPU想訪問VP3頁面中的某一個字節。會發生什么情況?
由1.23小節的分析知,當地址翻譯硬件MMU找到了PTE3后,發現有效位為0,則說明VP3并未緩存在物理內存中,并且觸發一個缺頁異常。缺頁異常調用內核中的缺頁異常處理程序,該程序會在物理內存中查詢是否有空閑頁面。如果物理內存中有空閑頁面,則將VP3頁面的內容從磁盤中復制到(映射)物理內存中的空閑頁面。如果物理內存中沒有空閑頁面,則缺頁異常處理程序就選擇一個犧牲頁,在此例中就是存放在PP3中的VP4。如果VP4已經被修改了,那么內核就會將它復制回磁盤。
然后此時因為VP3已經在物理內存中被緩存了,就需要將頁表更新,也就是更新PTE3。
隨后缺頁異常處理程序返回。它會重新啟動導致缺頁的指令,該指令會重新將剛剛導致缺頁的虛擬地址發送到MMU硬件翻譯,但是此時,因為VP3已經被緩存,所以會頁命中。
下圖是在經過了缺頁后,我們的示例頁表的狀態:
- 以上有一個過程是替換頁面的過程,其中包含一個頁面調度算法。這個以后會學習。
1.25 分配頁面
當你在程序中調用malloc或者new分配內存時,發生了什么?調用malloc后,會在虛擬內存中分配頁面。(注意malloc分配的內存時虛擬內存,當CPU訪問的時候,首先肯定會發生缺頁,然后再將該頁緩存到物理內存中)
如下圖所示:
本身沒有VP5這個虛擬頁面,現在malloc后,新分配了一個虛擬頁面VP5。
分配好VP5這個虛擬頁面后,還需要更新PTE條目,使得PTE5指向VP5。
1.26 程序的局部性原則
虛擬內存這種機制會有什么問題?經常缺頁會不會導致程序的執行效率低下?
實際上,雖然會產生不命中現象,但是虛擬內存機制工作的很好。這主要與程序局部性原則有關!!!什么是程序的局部性?
盡管在程序整個運行的生命周期,引用的不同的頁面總數可能會超過物理內存的大小,但是局部性原則保證了在任意時刻:程序將趨向于在一個較小的活動頁面集合上工作。 這個集合成為工作集或者常駐集合。在最開始,也就是將工作集頁面調度到物理內存中之后,接下來對這個工作集的引用將導致頁命中,而不會產生額外的磁盤流量。
上面看似很完美,但是也有可能會出現這樣一種情況:工作集的大小超過了物理內存的大小!! 此時,頁面會不停的換入換出。這種狀態叫做抖動!!!
當然,現在的計算機的物理內存的大小都非常大,一般不會出現抖動的現象!!!
1.3 虛擬內存作為內存管理工具
虛擬內存為什么說是一種內存管理工具?
虛擬內存大大地簡化了內存管理,并提供了一種自然的保護內存的方法。
到目前為止,我們都假設有一個單獨的頁表,將一個虛擬地址空間映射到物理地址空間。實際上,操作系統為每一個進程提供了一個獨立的頁表,因而也就是一個獨立的虛擬地址空間。如下圖:
注意:多個虛擬頁面,可以映射到同一個共享物理頁面上。
按需頁面調度和獨立的虛擬地址空間的結合,對系統中內存的使用和管理產生了深遠的影響!!!如下:
- 簡化鏈接。
- 簡化加載
- 簡化共享
- 簡化內存分配
具體參考CSAPP:9.4節內容。
1.4、虛擬內存作為內存保護工具
上一節學習了虛擬內存作為內存管理工具。
其實虛擬內存還可以作為內存保護工具。如何做到?
想一想,CPU在訪問一個虛擬內存頁面時,需要讀取頁表條目中的PTE條目。如果在PTE條目中加一些額外的許可位來控制對虛擬內存的訪問,當CPU讀到相應的許可位,就可以知道該虛擬內存是否可讀或者可寫,或者可執行? 這樣看來我們的頁表就要變化一下,就如下圖所示:
上圖中:
- SUP表示進程是否必須運行在內核模式(超級用戶)下才能訪問該頁。
- READ表示是否可讀
- WRITE表示是否可寫
如果一條指令違反了這些許可條件,那么CPU就會觸發一個一般保護故障,將控制傳遞給一個內核中的異常處理程序。Linux shell 一般將這種異常報告為“段錯誤(segmentation fault)”
2、地址翻譯
上面一直在說MMU通過讀取頁表的PTE將虛擬地址翻譯成物理地址。到底是如何翻譯的?
如下圖,展示了MMU是如何翻譯地址的:
看到這么復雜的圖,不要害怕!!! 下面講解很容易懂!
- CPU中有一個控制寄存器,頁表基址寄存器(PTBR)指向當前頁表。
- n位的虛擬地址,包含兩個部分:虛擬頁面偏移VPO(p位)與虛擬頁號VPN(n-p位)
- MMU利用虛擬內存的高n-p位VPN作為索引找到頁表的對應的PTE條目,然后獲取PTE條目對應的物理頁號PPN
- 然后將PPN與VPO串聯連接起來,就得到了實際的物理地址。(實際上就是PPN左移p位然后加上VPO,VPO=PPO)
到這里實際上我們已經更加的將這種地址串聯與X86處理器中的分段機制很像。X86-16位的分段機制 也是將段地址CS左移4位然后與偏移地址IP相加,得到最終的物理地址。這是不是與上面的分頁機制的地址翻譯過程很像? 實際上它們一個是實模式,一個是保護模式而已!
MMU的地址翻譯過程是不是很簡單?如果不理解,就反復看,就理解了!!!
3、總結
下面來總結一下,分頁機制中,CPU獲得一個虛擬地址后,有哪些步驟需要做:
本片文章,我學會了:
-
虛擬內存的概念與交換區的概念
-
MMU的作用
-
虛擬內存機制的意義
- 虛擬內存作為內存管理工具
- 虛擬內存作為內存保護工具
-
頁表的概念
-
頁命中與缺頁
-
程序的局部性在虛擬內存中的作用
-
MMU的地址翻譯過程
本人積累了無數的技術電子書籍與各類技術的視頻教程,可以加好友共同探討學習交流。
學習探討加個人:
qq:1126137994
微信:liu1126137994
總結
以上是生活随笔為你收集整理的【软件开发底层知识修炼】三 深入浅出处理器之三 内存管理与内存管理单元(MMU)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: KNX教程
- 下一篇: 扩展插件_Adobe扩展工具插件系列