虛擬記憶體與記憶體映射

多層分頁表

為 64 位元定址空間準備一個扁平分頁表會大得不可能——其中大部分都涵蓋著沒有程式碰過的位址。解法和圖書館不用一張巨型索引卡、而用一棵較小表所組成的樹一樣:你只建立你真正造訪的分支。多層分頁表(multi-level page table)是一個表的層級結構,每一層把位址縮小一點,直到最後一層指出頁框。

以下用淺白步驟說明查詢如何「走」這棵樹,採 x86-64 上常見的四層架構。虛擬分頁號碼被切成數個小段,每層一段。頂層暫存器(cr3)指向第一層表;位址的第一段拿去索引它,找到第二層表的實體位址;下一段索引那張表,找到第三層表;以此類推,直到最後一段索引最後一張表、得到頁框,再與偏移量結合。好處是稀疏性:若定址空間有一整塊沒用到,它對應的上層表項就直接標成空的,底下的表根本不存在,於是一個只用幾 MiB 的行程只需要少少幾張小表,而不是一張巨大的扁平表。

代價是現在一次完整轉譯需要好幾次記憶體讀取(每層一次)——這稱為「分頁表走訪(page-table walk)」。這正是 TLB 存在的原因:它快取最終答案,讓常見路徑跳過這多層走訪。日常寫程式時你很少想到層數,但這個結構解釋了為什麼碰觸四處亂散的位址,會比碰觸鄰近的位址慢(更多 TLB 未命中、更多走訪)。

在 x86-64 上採四層、4 KiB 分頁時,48 位元的虛擬分頁號碼被切成四個 9 位元的索引外加 12 位元的偏移量。硬體依序讀四張表,每個索引挑出下一張表,直到第四張給出頁框。若只用了 8 MiB,上層的表項幾乎全是空的,因此只存在寥寥幾張表。

四張小表,取代一張大得不可能的扁平表。

層數越多,表越稀疏、越省儲存,但 TLB 未命中時的走訪越長。這棵樹之所以省記憶體,正是因為沒用到的區域不花任何成本;這也是為什麼一個行程能擁有巨大的定址空間,實際的分頁表佔用卻很小。

又稱
hierarchical page tablepage-table tree層級式分頁表