妙趣橫生的虛擬存儲器


寫在前面的

閱讀這篇文章需要計算機組成原理的基礎. 在這里外鏈上一篇文章《關於讀書的流水賬》,有讀書感受。虛擬存儲器的核心思想很獨到,在看了前一篇文章中提到的書中才領略到了它的魅力,硬件的東西比較多,但是也絕對可以提高你的軟件功力,而且毫無疑問。這篇文章算是讀書筆記。

PS:發現文中有很多的英文簡寫,為了方便閱讀在這里總結一下。

------------------------------------------------------------------------ 
中文 | 英文,英文簡寫   
------------------------------------------------------------------------

物理地址 | Physical Address,PA

------------------------------------------------------------------------ 

物理尋址 | Physical Addressing
------------------------------------------------------------------------ 
虛擬地址 | Virtual Addressing,VA
------------------------------------------------------------------------ 
虛擬存儲器 | Virtual Memory
------------------------------------------------------------------------ 
物理頁 | Physical Page,PP
------------------------------------------------------------------------ 
虛擬頁 | Virtual Page,VP
------------------------------------------------------------------------ 
隨機訪問存儲器 | Random Access Memory  //物理存儲器,內存
------------------------------------------------------------------------ 
| Page Table,PT
------------------------------------------------------------------------ 

頁表條目 | Page Table Entry,PTE
------------------------------------------------------------------------ 
虛擬地址 | Virtual Addressing,VA 
------------------------------------------------------------------------ 
  

物理地址和虛擬地址

把主存看成是由連續字節單元組成的大數組,並且用物理地址(PA)來標識每個數組的單元。CPU需要加載存儲器中一個字都時候,就指定這個字的物理地址的首地址,從而將存儲器中的數據返回給CPU,通過物理地址來訪問存儲器的方式就是物理尋址。所以很直觀,物理尋址方便很多,然而對於系統來說,直接物理尋址對存儲器的管理很不合理。
image
所以有了虛擬地址(VA),通過虛擬地址訪問存儲器的方式就叫做虛擬尋址,其實這種說法不是很恰當,因為虛擬地址最終還是會被翻譯(這個翻譯由硬件和系統協同完成的)成物理地址,從而訪問存儲器。另外,虛擬地址和物理地址是一一對應的,頁就是全相聯的。
image

可以看到,最終訪問內存的還是物理地址(PA)。

 

注意啦,虛擬存儲器

image

虛擬存儲器,是由N個字節組成的,它存在於磁盤上(注意,是磁盤上,不是存儲器內存上)。另外物理存儲器和虛擬存儲器都是用頁來作為磁盤和內存的傳輸單元。但是CPU是從內存(或者是cache)上取數據啊,而虛擬存儲器是存在在磁盤上,因此虛擬存儲器必須清楚它的哪些頁是已分配(里面的數據是有效的)的,哪些是緩存在內存中(將數據從磁盤中拷貝到CPU能較高速訪問物理存儲器)的,哪些是已分配但是未被緩存到內存中的(數據是有效的且暫時只存在磁盤中,當需要的時候再緩沖)。

 

啊哈,神奇的頁表

虛擬存儲器如何知道它每個頁的分配情況呢?頁表(PT)從而誕生了,每一個虛擬存儲器都有它自己獨有的頁表,頁表為虛擬地址和物理地址的全相聯提供了可能。
image 

因為有頁表的存在,所以沒有必要把虛擬存儲器(再聲明,是存在在磁盤上的)的所以頁都緩存在內存當中,即便CPU訪問該虛擬存儲器的頁不存在在內存當中,那么系統會通過查表,把需要的頁從磁盤當中拷貝到內存當中,這里就涉及了頁面調度的復雜算法了,而且這種算法不是單一的,這里只簡單做個介紹。

 

有了頁表,CPU也不放心

頁命中的情況,如果虛擬頁已經緩存到了物理存儲器那么好辦,直接從物理存儲器中直接讀取數據就好了。
image  
還是這張圖,來看看簡單的命中的情況。假如CPU給出的虛擬地址,地址翻譯硬件進行查表,通過虛擬地址定位到了PTE 2(PTE就是頁表的條目,上面有注釋)的位置,發現它的有效位是1,證明里面的數據是有效的且數據已經緩存到了DRAM當中。所以取出PTE 2中的物理存地址來訪問DRAM,可以看到它指向了DRAM中的VP 0,目標查找成功,OVER!!

但是頁不命中(缺頁)的情況,那就有點麻煩了。
 image 還是這張圖,只是修改了一下,CPU給出的虛擬地址指向了尚未緩沖的地址。地址翻譯硬件發現PTE 5中數據是有效的,但它並沒有從磁盤中緩存到DRAM中。地址翻譯硬件發現某個CPU需要的虛擬頁沒有緩存到DRAM中,就會觸發一個缺頁的異常,那么對應的缺頁異常處理程序就會啟動。首先會選擇已緩存到DRAM的一個犧牲頁,把它拷貝會虛擬存儲器的某個位置,再將命中的虛擬頁緩存到DRAM當中。
這時候,異常處理過程返回,重新返回到導致缺頁異常的指令,重新執行,目標命中,OVER!!另外,經常缺頁會降低程序執行的效率,不命中的處罰還是存在的。

 

對於缺頁,是什么解決了CPU的煩惱 

這時候有個疑問了,CPU給出的虛擬地址經常不命中,即使有頁面的調度,也會大大降低程序執行的效率。 還好,有局部性存在。局部性包括時間局部性和空間局部性。

時間局部性就是程序的數據能夠被重復或者多次引用或者被CPU讀取。空間局部性就是CPU要執行的指令或者引用的數據在一段存儲空間內。因此局部性能夠在一定的程度上降低不命中的可能性。

 

進程離不開虛擬存儲器

在這里不得不扯上進程這東西。操作系統為每個進程都分配了一個頁表,也就是說每個一個進程都有個虛擬存儲器,獨立的虛擬地址空間。
image  

所以可以看到,每個進程都有一張頁表,所以同一個進程的存儲空間在虛擬存儲器中可以是不連續的,因為虛擬存儲器和頁表映射加上缺頁緩存的機制讓進程“擁有”一個“連續”的空間提供了可能,可實際上,是很有可能是不連續的。CPU提取數據的時候,都會先給出的是虛擬地址,無論頁命中還是不命中,最后由地址翻譯硬件翻譯出來的物理地址都不會有錯。

在剛開始學c語言的時候經常用到函數scanf和printf等等一些函數,他們在自己進程中有一個虛擬地址與之對應,這樣看起來好像每個進程內scanf和printf是分家的,實際上,由於虛擬地址的映射,每個進程中的這些庫函數地址都映射到了物理地址的同一個位置,這就節省了很多的空間,從而又不影響進程的獨立性。不得不自己親手畫一張在深入理解計算機系統一書中的一個叫做“進程的虛擬地址空間”圖,非常經典。
image

對於32位的系統,進程的虛擬地址空間有4G(其中包括了內核的和進程本身的),那難道4G都要一一映射到虛擬存儲器中?當然不是,進程虛擬空間上有空隙的,也就是說,頁表中只記錄了有效的虛擬頁。在這里看到了我經常從自己嘴里蹦出來的堆棧雲雲,看了這里我對堆棧有了更近一步的了解,疑雲頓消。

  一本好書真的可以勝過老師在課堂上講,而且毫無疑問。

 

收獲都在上面了。

本文完 Thursday, April 26, 2012

搗亂小子 http://daoluanxiaozi.cnblogs.com/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM