> 緣起
《深入Linux內核架構》P144頁。讀書存疑,繼而想通。
深入Linux內核架構 PDF(中文版+英文版) 下載見 http://www.linuxidc.com/Linux/2012-06/62984.htm
> 鋪墊
虛擬地址空間一般按3:1劃分為進程地址空間和內核地址空間,32位機器4G的虛擬地址空間就有1G分為內核地址空間。
(1) 內核地址空間前896M是直接映射的物理頁幀,即物理內存上的896M能直接映射(通過線性偏移0xC000000)到內核地址空間的這個區域。
(2) 然後是一小段內存間隙用於內核故障報錯。
(3) 然後是vmalloc區域,用於動態分配,內核自身會盡力避免非連續的物理地址,這段內存區主要用於動態加載模塊時。
(4) 然後是2個頁幀的保護性間隔內存。
(5) 然後是持久映射區,用於將highmemory中的非持久頁映射到內核中。(存疑,暫不求甚解)
(6) 最後是固定映射區,一直到虛擬地址4GB處。對於上面所述的直接映射區,虛擬地址平移__PAGE_OFFSET(IA-32上即為0xC000000)即得到物理地址,而固定映射不同,這個區域中的虛擬地址指向隨機的物理地址,虛擬地址和物理地址的關聯可以自由定義但定義後不能改變。固定映射的優點是:1. 編譯時對此類地址的處理類似常數,內核一啟動即為其分配了物理地址。 2. 此類地址的反引用比普通指針要快。 3. 內核確保在上下文切換時,對應於固定映射的頁表項不會從TLB刷出,在訪問固定映射的內存時,總是通過TLB高速緩存取得對應的物理地址。
> 正文
對每個固定映射地址都會創建一個常數,加入到fixed_addresses枚舉值列表中,__end_of_fixed_addresses是最後一個枚舉成員,定義了最大的可能數字。 linux_kernel_2.6.27.62/include/asm-x86/fixmap_32.h :: fix_to_virt()函數用於根據固定映射的fixed_addresses常數計算虛擬地址