1. 程式人生 > >linux-----頁、頁表、頁框(塊)

linux-----頁、頁表、頁框(塊)

基本介紹
我們知道,在linux作業系統中,CPU在執行一個程序的時候,都會訪問記憶體。
但CPU並不是直接訪問實體記憶體地址,而是通過虛擬地址空間來間接的訪問實體記憶體地址。
所謂的虛擬地址空間,是作業系統為每一個正在執行的程序分配的一個邏輯地址,在32位機上,其範圍從0 ~ 4G-1。作業系統通過將虛擬地址空間和實體記憶體地址之間建立對映關係,讓CPU間接的訪問實體記憶體地址。
通常將虛擬地址空間以512Byte ~ 8K,作為一個單位,稱為,並從0開始依次對每一個頁編號。這個大小通常被稱為頁面
將實體地址按照同樣的大小,作為一個單位,稱為或者,也從0開始依次對每一個框編號。
作業系統通過維護一張表,這張表上記錄了每一對頁和框的對映關係。如圖:
頁-頁表-框


這張表,稱為頁表
在windows系統下,頁面為4k,這裡我們以4k為例。
一個4G虛擬地址空間,將會產生1024*1024個頁,頁表的每一項儲存一個頁和一個框的對映,所以,至少需要1M個頁表項。如果一個頁表項大小為1Byte,則至少需要1M的空間,所以頁表被放在實體記憶體中,由作業系統維護。
當CPU要訪問一個虛擬地址空間對應的實體記憶體地址時,先將具體的虛擬地址A/頁面大小4K,結果的商作為頁表號,結果的餘作為業內地址偏移。
例如:
CPU訪問的虛擬地址:A
頁面:L
頁表號:(A/L)
頁內偏移:(A%L)
CPU中有一個頁表暫存器,裡面存放著當前程序頁表的起始地址和頁表長度。將上述計算的頁表號和頁表長度進行對比,確認在頁表範圍內,然後將頁表號和頁表項長度相乘,得到目標頁相對於頁表基地址的偏移量,最後加上頁表基地址偏移量就可以訪問到相對應的框了,CPU拿到框的起始地址之後,再把頁內偏移地址加上,訪問到最終的目標地址。如圖:
地址轉換過程

注意,每個程序都有頁表,頁表起始地址和頁表長度的資訊在程序不被CPU執行的時候,存放在其PCB內。
按照上述的過程,可以發現,CPU對記憶體的一次訪問動作需要訪問兩次實體記憶體才能達到目的,第一次,拿到框的起始地址,第二次,訪問最終實體地址。CPU的效率變成了50%。為了提高CPU對記憶體的訪問效率,在CPU第一次訪問記憶體之前,加了一個快速緩衝區暫存器,它裡面存放了近期訪問過的頁表項。當CPU發起一次訪問時,先到TLB中查詢是否存在對應的頁表項,如果有就直接返回了。整個過程只需要訪問一次記憶體。如圖:
快表
這種方式極大的提高了CPU對記憶體的訪問效率。將近90%。
然而這樣的方式還是存在弊端,在實體記憶體中需要拿出至少1M的連續的記憶體空間來存放頁表。可以通過多級頁表的方式,將頁表分為多個部分,分別存放,這樣就不要求連續的整段記憶體,只需要多個連續的小段記憶體即可。
把連續的頁表拆分成多個頁表稱之為一級頁表,再建立一張頁表,這張頁表記錄每一張一級頁表的起始地址並按照順序為其填寫頁表號。
通過這樣的方式,CPU從基地址暫存器中拿到了一級頁表的地址,從地址結構中取出一級頁表的頁表號,找到二級頁表的起始實體地址;然後結合地址結構中的中間10位(二級頁表上的頁表號),可以找到對應的框的起始地址,最後結合頁內偏移量,就可以計算出最終目標的實體地址。如圖:
多級頁表