《深刻理解linux內核》第二章 內存尋址
-
-
三種不一樣的內存地址
- 邏輯地址(logical address)包含在linux實際指令中的地址,即分段式地址,是對應的硬件平臺段式管理轉換前地址
由16位的段選擇符(segment selector)和32位的偏移量組成。
- 線性地址(linear address)(虛擬地址(virtual address))是一個32位無符號整數,能夠表示4G的地址,值範圍從0x00000000-0xffffffff。
線性地址則對應了硬件頁式內存的轉換前地址。
- 物理地址(physical address)
用32位或者36位無符號整數表示。用於內存芯片級的單元尋址,與處理器和CPU鏈接的地址總線相對應。
- 三者之間的關係邏輯地址------>分段單元------>線性地址------>分頁單元------>物理地址
-
硬件中的分段
- 段選擇符和段寄存器
如圖所示,16位段選擇符的最後13位是索引號,第0和1位是2bit位的請求者特權等級(一共有4中特權等級,linux只使用內核態仍是用戶態),第2位爲表指示器。
段寄存器有css,ss,ds,es,fs,gs。其中前三個有特殊用途,後三個是通用段寄存器。
- 段描述符(segment descriptor)
段描述符表放在全卷描述符表(global descriptor table)GDT或者局部描述符表(local descriptor table) LDT 中。
具體的段描述符表類型能夠看這裏:http://www.sandpile.org/x86/desc.htm
- 邏輯地址轉線性地址過程
過程分三步:
- 檢查段寄存器中的TI和RPL標誌,肯定段描述符在GDT仍是LDT中;
- 把段寄存器INDEX的值*8+GDT/LDT中保存的地址,便可獲得段描述符地址。(該地址在64位處理器是64位,在32位處理器是32位)。
若是咱們用GDB調試程序時,觀察幾個段寄存器的值,能夠和本書及linux源碼中的預設值獲得印證。段寄存器的INDEX的值正好是在段描述符表中所在的位置。且64位和32位的區別很大。
- 把邏輯地址的便宜量和段描述符的BASE字段相加便可獲得線性地址。
-
LINUX中的分頁
- 32位系統未開啓地址擴展
CR3===>PGD(10)==>PT(10)==>OFFSET(12) 此時頁目錄項和頁表項是32位的,每一個頁表正好在一個頁上,恰好是2^10*4Byte=4096kb 恰好是一頁。
- 32位開啓物理地址擴展
CR3==>PGD(2)==>PMD(9)==>PT(9)==>OFFSET(12) 此時頁目錄項和頁表項都是64位,但他們是9位的,因此每一個頁表佔用的恰好是2^9*8Byte 恰好也是一頁
- 64位系統
CR3==>PGD(9)==>PUD(9)==>PMD(9)==>PT(9)==>OFFSET(12)
個人博客:www.while0.com
歡迎關注本站公眾號,獲取更多信息