《深刻理解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
相關文章
相關標籤/搜索