兩級頁表如何實現地址轉換:
- 頁表:是一種特殊的數據結構,記錄著頁面和頁框的對應關系。(映射表)
- 頁表的作用:是內存非連續分區分配的基礎,實現從邏輯地址轉化成物理地址。
- (1) 按照地址結構將邏輯地址拆成三個部分。
- (2) 從PCB中讀取頁目錄起始地址,再根據一級頁號查頁目錄表,找到下一級頁表在內存中存放位置。
- (3) 根據二級頁號查表,找到最終想要訪問的內存塊號。
- (4) 結合頁內偏移量得到物理地址。
虛擬存儲技術
再解決了頁必須連續存放的問題后,再看如何第二個問題:沒有必要讓整個頁表常駐內存,因為進程一段時間內可能只需要訪問某幾個特定的頁面。
解決方案:可以在需要訪問頁面時才把頁面調入內存——虛擬存儲技術(后面再說)。可以在頁表中增加一個標示位,用于表示該頁表是否已經調入內存。
應用
若采用多級頁表機制,則各級頁表的大小不能超過一個頁面。
舉例說明,某系統按字節編址,采用40位邏輯地址,頁面大小為4KB,頁表項大小為4B,假設采用純頁式存儲,則要采用()級頁表,頁內偏移量為()位?
頁面大小 = 4KB,按字節編址,因此頁內偏移量為12位。
頁號 = 40 - 12 = 28位。
頁面大小 = 4KB,頁表項大小 = 4B,則每個頁面可存放1024個頁表項。因此各級頁表最多包含1024個頁表項,需要10個二進制位才能映射到1024個頁表項,因此每級頁表對應的頁號應為10位二進制。共28位的頁號至少要分為3級。
1、 進程的4G 線性空間被劃分成三個部分:進程空間(0-3G)、內核直接映射空間(3G – high_memory)、內核動態映射空間(VMALLOC_START - VMALLOC_END)
2、 三個空間使用同一張頁目錄表,通過 CR3 可找到此頁目錄表。但不同的空間在頁目錄表中頁對應不同的項,因此互相不沖突
3、 內核初始化以后,根據實際物理內存的大小,計算出 high_memory、VMALLOC_START、VMALLOC_END 的值。并為“內核直接映射”空間建立好映射關系,所有的物理內存都可以通過此空間進行訪問。
4、 “進程空間”和“內核動態映射空間”的映射關系是動態建立的(通過缺頁異常)
假設在有三個線性地址 addr1, addr2, addr3 ,分別屬于三個線性空間不同部分(0-3G、3G-high_memory、vmalloc_start-vmalloc_end),但是最終都映射到物理頁面1:
1、 三個地址對應不同的頁表和頁表項
2、 但是頁表項的高 20bit 肯定是1,表示物理頁面的索引號是1
3、 同時,根據高 20 bit,可以從 mem_map[] 中找到對應的 struct page 結構,struct page 用于管理實際的物理頁面(就是實際物理頁面的物理地址了,到這里就不繞彎子了,順便想到高速緩沖的匹配命中操作是用哈希表,換算出的要訪問的實際物理地址拿到哈希表的輸入計算一下哈希值,看看有沒命中)(紅線)
4、 從線性地址最終的,根據頁目錄表,頁表,可以找到物理地址
5、 Struct page 和物理地址之間很容易互相轉換
6、 從物理地址,可以很容易的反推出在內核直接映射空間的線性地址(藍線)。要想得到在進程空間或者內核動態映射空間的對應的線性地址,則需要遍歷相應的“虛存區間”鏈表。
關于頁目錄表:
1、 每個進程有一個屬于自己的頁目錄表,可通過 CR3 寄存器找到
2、 而內核也有一個獨立于其它進程的頁目錄表,保存在 swapper_pg_dir[] 數組中
3、 當進程切換的時候,只需要將新進程的頁目錄把地址加載到 CR3 寄存器中即可
4、 創建一個新進程的時候,需要為它分配一個 page,作為頁目錄表,并將 swapper_pg_dir[] 的高 256 項拷貝過來,低 768 項則清0
linux0.11版本,所有進程共享同一個頁目錄而各自使用不同的頁表,該共享的頁目錄就放在物理地址最前面的4k
標題:Linux系統文件頁表目錄和頁表結構(圖文詳解)
原文作者:玩轉Linux內核,地址:https://zhuanlan.zhihu.com/p/429914858 轉載注明來源
-
嵌入式
+關注
關注
5068文章
19019瀏覽量
303308 -
內核
+關注
關注
3文章
1363瀏覽量
40228 -
Linux
+關注
關注
87文章
11229瀏覽量
208931
發布評論請先 登錄
相關推薦
評論