Linux下邏輯地址、線性地址、實體地址詳細總結
二、線性地址轉實體地址
前面說了Linux中邏輯地址等於線性地址,那麼線性地址怎麼對應到實體地址呢?這個大家都知道,那就是通過分頁機制,具體的說,就是通過頁表查詢來對應實體地址。
分頁是CPU提供的一種機制,Linux只是根據這種機制的規則,利用它實現了記憶體管理。
分頁的基本原理是把線性地址分成固定長度的單元,稱為頁(page)。頁內部連續的線性地址對映到連續的實體地址中。X86每頁為4KB(為簡化分析,我們不考慮擴充套件分頁的情況)。為了能轉換成實體地址,我們需要給CPU提供當前任務的線性地址轉實體地址的查詢表,即頁表(page table),頁表存放在記憶體中。
在保護模式下,控制暫存器CR0的最高位PG位控制著分頁管理機制是否生效,如果PG=1,分頁機制生效,需通過頁表查詢才能把線性地址轉換實體地址。如果PG=0,則分頁機制無效,線性地址就直接作為實體地址。
為了實現每個任務的平坦的虛擬記憶體和相互隔離,每個任務都有自己的頁目錄表和頁表。
為了節約頁表佔用的記憶體空間,x86將線性地址通過頁目錄表和頁表兩級查詢轉換成實體地址。
32位的線性地址被分成3個部分:
最高10位 Directory 頁目錄表偏移量,中間10位 Table是頁表偏移量,最低12位Offset是物理頁內的位元組偏移量。
頁目錄表的大小為4KB(剛好是一個頁的大小),包含1024項,每個項4位元組(32位),表項裡儲存的內容就是頁表的實體地址(因為物理頁地址4k位元組對齊,實體地址低12位總是0,所以表項裡的最低12位元組記錄了一些其他資訊,這裡做簡化分析)。如果頁目錄表中的頁表尚未分配,則實體地址填0。
頁表的大小也是4k,同樣包含1024項,每個項4位元組,內容為最終物理頁的實體記憶體起始地址。
每個活動的任務,必須要先分配給它一個頁目錄表,並把頁目錄表的實體地址存入cr3暫存器。頁表可以提前分配好,也可以在用到的時候再分配。
還是以 mov 0x80495b0, %eax 中的地址為例分析一下線性地址轉實體地址的過程。
前面說到Linux中邏輯地址等於線性地址,那麼我們要轉換的線性地址就是0x80495b0。轉換的過程是由CPU自動完成的,Linux所要做的就是準備好轉換所需的頁目錄表和頁表(假設已經準備好,給頁目錄表和頁表分配實體記憶體的過程很複雜,後文再分析)。
核心先將當前任務的頁目錄表的實體地址填入cr3暫存器。
線性地址 0x80495b0 轉換成二進位制後是 0000 1000 0000 0100 1001 0101 1011 0000,最高10位0000 1000 00的十進位制是32,CPU檢視頁目錄表第32項,裡面存放的是頁表的實體地址。線性地址中間10位00 0100 1001 的十進位制是73,頁表的第73項儲存的是最終物理頁的物理起始地址。物理頁基地址加上線性地址中最低12位的偏移量,CPU就找到了線性地址最終對應的實體記憶體單元。
我們知道Linux中使用者程式線性地址能定址的範圍是0 - 3G,那麼是不是需要提前先把這3G虛擬記憶體的頁表都建立好呢?一般情況下,實體記憶體是遠遠小於3G的,加上同時有很多程式都在執行,根本無法給每個程式提前建立3G的線性地址頁表。Linux利用CPU的一個機制解決了這個問題。程式建立後我們可以給頁目錄表的表項值都填0,CPU在查詢頁表時,如果表項的內容為0,則會引發一個缺頁異常,程式暫停執行,Linux核心這時候可以通過一系列複雜的演算法給分配一個物理頁,並把物理頁的地址填入表項中,程式再恢復執行。當然程式在這個過程中是被矇蔽的,它自己的感覺還是正常訪問到了實體記憶體。
怎樣防止程式訪問不屬於自己的線性地址(如核心空間)或無效的地址呢?核心裡記錄著每個程式能訪問的線性地址範圍(程式的vm_area_struct 線性區連結串列和紅黑樹裡存放著),在引發缺頁異常的時候,如果核心檢查到引發缺頁的線性地址不在程式的線性地址範圍內,就發出SIGSEGV訊號,程式結束,我們將看到程式設計師最討厭看到的Segmentation
fault。
相關文章
- 實體地址、虛擬地址
- 07_Linux實體地址到虛擬地址對映Linux
- 已知結構體成員地址獲取結構體首地址結構體
- 你看到的所有地址都不是真的 | 虛擬地址與實體地址
- 常用AIX論壇地址、資料下載地址、FTP地址AIFTP
- iphone 獲取地址的詳細資訊iPhone
- Linux下修改MAC地址LinuxMac
- linux下配置IP地址Linux
- CVS相關工具下載地址總結
- nginx取結構體地址Nginx結構體
- wince5.0下實體地址訪問
- linux常用開源軟體下載地址Linux
- 下載地址
- Linux RPM 下載地址Linux
- IP地址詳解
- 實體“微地址”的遐想
- 《網路IP地址管理》IP地址重要性薦
- PL/SQL Developer下載地址和漢化包地址SQLDeveloper
- IP地址網段表示法總結
- SQLSERVER下載地址SQLServer
- redhat 下載地址Redhat
- heartbeat下載地址
- OpenSuse 下載地址
- monocloud下載地址MonoCloud
- IP地址結構
- MAC 地址與IP地址Mac
- linux版 myeclipse 下載地址LinuxEclipse
- Oracle Linux 6.2快速下載地址OracleLinux
- 實用Linux下獲取公網IP地址Linux
- 有道翻譯軟體下載地址
- ARP地址解析協議-個人總結協議
- android學習地址和文章總結Android
- 取本頁URL地址的方法總結
- linux修改IP地址Linux
- Oracle Enterprise Linux 下載地址OracleLinux
- Linux下設定靜態IP地址Linux
- linux下bind一個非本地地址Linux
- 使用者態程式的虛擬地址如何轉換成實體地址