今天在思考一個可能由page table引發的Linux操作系統內存報警問題時發現基礎知識缺失的太多,因此找了幾本操作系統相關的書復習了一下,在這里記下來。
首先上一幅32位尋址空間的虛擬地址結構圖:(僅適用于一級頁表,頁面大小為4KB)
前12位表示頁內偏移量,后20位表示頁號,可尋址2^20=1M個頁,假如頁面大小為4KB,那么就能尋址4GB的虛擬地址。
那么這樣一個32位的虛擬地址是如何轉換為物理地址的呢?
下圖說明了一切:
圖1.分頁系統的地址變換機構 --摘自《計算機操作系統》湯小丹版
尋址步驟解析:
1.首先假設虛擬地址為A,頁面大小為L,則可以通過以下公式迅速計算出相應的頁號P和頁內偏移量d:
P=INT [A/L] --除法取整
d=A%L --求余
2.得到P和d之后,使用P與頁表寄存器中的寄存的頁表始址(一個物理地址),進行邏輯運算得到頁表項的具體位置。(其實就是通過頁表始址找到頁表頁,再在里邊找到頁號)
3.在此頁表項中取到后半截的塊號--通過塊號得到塊的物理始址,通過這個物理始址與頁內偏移量相加得到真正的物理地址。
整個過程很簡單,就兩個加法,兩次尋址。
舉例說明:
一個頁表的結構如下所示:(這里省了標識頁表的始址,直接給了頁表的內容)
頁號 塊號 0 3 1 2 2 0 3 1
假設有一個虛擬地址0x000B,頁面大小為4KB(0x1000),那么:
1.P=0x000B/0x1000=0; d=0x000B%0x1000=0x000B;因此頁號為0,頁內偏移量為0x000B
2.通過與寄存器的邏輯運算找到如上頁面的0頁號,發現0號對應物理塊號是3
3.3*0x1000+0x000B=0x300B
因此真實的物理地址就是0x300B。
拓展知識:
由于頁表空間必須是連續的內存地址,這樣的開銷在32位分頁系統中幾乎是不可接受的,因此我們一般采用如下兩種辦法解決此問題:
1.多級頁表,即頁表的頁表,這樣頁表可以離散的分布于內存之中,不必是連續內存,64位尋址空間的分頁系統常見3級頁表,32位的常見兩級頁表。
2.只緩存一部分的頁表,其他頁表部分在外存中,根據需要調入,這樣解決了頁表空間占用的問題;對于多級頁表,其外部頁表必須調入內存,頁表則可以只緩存一部分。
現在常見的64位操作系統一般采用多級頁表的方式,大多數為3級頁表,其實就是頁表3級索引,因此CPU多出了2個頁表寄存器來記錄多級頁表的物理始址,但是本質與一級頁表尋址方式類似。
自2.6.11內核版本以來,Linux采用4級頁表的分頁方式(9+9+9+12)。
在64位分頁系統中,由于可尋址范圍已經大大擴展,因此所有的頁目錄和頁表都已被存入內存。
對于用戶空間和內核空間,以及高端內存、低端內存還有線性映射、非線性映射等概念,在64位分頁系統中應當全部舍棄,除非你是研究內核的。
最后再放一個段頁式邏輯地址-->線性地址(虛擬地址)-->物理地址的轉換圖:
文章列表
留言列表