閱讀484 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Linux內核剖析 之 內存尋址(二)

//接前一篇博客:

本節主要介紹硬件中分頁機製。

4、線性地址->物理地址(分頁:硬件部分

       為了效率,線性地址被分成以固定長度為單位的組,稱為頁(Page),頁內部連續的線性地址被映射到連續的物理地址中。

      分頁單元把所有的內存分成固定長度的頁框(page frame)。每個頁框包含一個頁(page),也就是說一個頁框的長度與一個頁的長度一致。頁框是主存的一部分,因此是一個存儲區域。頁和頁框是不同的,也隻是一個數據塊,可以存放在任何頁框或磁盤中。

4.1、分頁

      從80386起,Intel處理器的分頁單元處理4KB的頁。

      32位線性地址被分成3個域:

      *Directory(目錄):最高10位

      *Table(頁表):中間10位

      *Offset(偏移量):最低12位

      線性地址的轉換分兩步完成:

      *頁目錄表轉換;

      *頁表轉換。

      使用二級模式的目的在於減少每個進程頁表所需內存的數量。

 

      控製寄存器cr3中存放正在使用的頁目錄的物理地址。線性地址內的Directory字段決定頁目錄中的目錄項,而目錄項指向適當的頁表。地址的Table字段依次又決定頁表中的表項,而頁表含有頁所在頁框的物理地址。Offset字段決定頁框內的相對位置。由於Offset字段是12位長,故每一頁含有4096B的數據。


      頁目錄項和頁表項具有相同的結構每項包含下麵的字段

      *Present標誌:

      置1,所指頁或頁表在主存中;為0,不在主存中。如果當訪問一個地址時,頁目錄項或頁表項的Present標誌為0,則分頁單元將該線性地址存放在寄存器cr2中,產生14號異常:缺頁異常。

      *Field 標誌

      20位,頁目錄項中的Field指向包含一個頁表的頁框。頁表項中的Field指向包含一頁數據的頁框。

      *PCD/PWT 標誌控製硬件高速緩存處理頁或頁表的方式。

      *Accessed 標誌:每當分頁單元對相應頁框進行尋址時,設置這個標誌。分頁單元從來不重置這個標誌,而是必須由操作係統去做。

      *Dirty 標誌:隻應用於頁表項中,每當對一個頁框寫操作時就設置。分頁單元從來不重置這個標誌,而是必須由操作係統去做。

      *Read/Write:頁或頁表的存取權限。與段的3種存取權限(讀、寫、執行)不同的是,頁的存取權限隻有兩種(讀、寫)。如果Read/Write標誌為0,說明相應的頁表或頁是隻讀的,否則是可讀寫的。

      *User/Supervisor:訪問頁或頁表所需的特權級。若此標誌為0,隻有當CPL小於3(Linux:CPU處於內核態)時才能對頁尋址,否則總能對頁尋址。

      *Page Size:隻應用於頁目錄項。設置為1,則頁目錄項指向2M或4M的內存。(hugepage)

      *Global標誌:隻應用於頁表項,用於防止常用頁(全局頁)從TLB中刷新出去。(當cr4寄存器的PGE(頁全局啟用)標誌置位時,這個標誌才有效)


      ##擴展分頁:(頁框大小為4MB而不是4KB)

      ——通過設置cr4處理器寄存器的PSE標誌能使擴展分頁與常規分頁共存。

 

     對於2M頁麵,啟動時傳遞內核參數

hugepages=1024 

     對於1GB的頁麵:

default_hugepagesz=1G hugepagesz=1G hugepages=4

    CPU所支持的hugepage大小可以由cpu標誌得知

If pse exists, 2M hugepages are supported; if pdpe1gb exists, 1G hugepages are supported.

For 2 MB pages, there is also the option of allocating hugepages after the system has booted.


echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

 

mkdir /mnt/huge

mount -t hugetlbfs nodev /mnt/huge

      隻要是在 /mnt/huge/ 目錄下創建的文件,將其映射到內存中時都會使用 2MB 作為分頁的基本單位。值得一提的是,hugetlbfs 中的文件是不支持讀 / 寫係統調用 ( 如read()或write()等 ) 的,一般對它的訪問都是以內存映射的形式進行的。

     在實際應用中,為了使用大頁麵,還需要將應用程序與庫libhugetlb鏈接在一起。libhugetlb庫對malloc()/free()等常用的內存相關的庫函數進行了重載,以使得應用程序的數據可以放置在采用大頁麵的內存區域中,以提高內存性能。


      ##物理地址擴展(PAE)分頁機製:

      物理地址擴展(Physical Address ExtensionPAE)用於將32位線性地址轉換為36位物理地址。

      通過設置cr4控製寄存器中的PAE標誌激活PAE

      PAE分頁機製:

      *64GBRAM被分為2^24個頁框,頁表項的物理地址字段從20位擴展到了24位。一個4KB的頁表包含512個表項而不是1024個表項。

      *引入頁目錄表指針表(Page Directory Pointer TablePDPT)的頁表新級別,它由464為表項組成。

      *cr3控製寄存器包含一個27為的頁目錄指針表(PDPT)基地址字段。

      *當把線性地址映射到4KB的頁時,32位線性地址按下列方式解釋:

      Cr3:指向一個PDPT

      位31-30:指向PDPT4個項的一個;

      位29-21:指向頁目錄表中512個項中的一個;

      位20-12:指向頁表中512項中的一個;

      位11-04KB頁中的偏移量。

     *當把線性地址映射到2MB的頁時,32位線性地址按下列方式解釋:

      Cr3:指向一個PDPT

      位31-30:指向PDPT4個項的一個;

      位29-21:指向頁目錄表中512個項中的一個;

      位20-02MB頁中的偏移量。


4.2 加快線性地址轉換

      為了縮小CPURAM之間的速度不匹配,引入了硬件高速緩存。基於局部性原理。

      #cache line :高速緩存與內存間一次傳輸數據的長度。

      #PCD 當訪問該頁框中數據時,高速緩存功能被啟用還是禁用。

      #PWT:當數據被寫到頁框時,采用通寫策略還是回寫策略。

      Linux對所有頁框都啟用高速緩存,對寫操作都采用回寫策略。

 

      TLB(Translation Lookaside Buffer):轉換後援緩衝器。

      在多處理器係統中,每個CPU都有自己的TLB,稱為本地TLB

      機製:當一個線性地址第一次使用時,通過慢速訪問RAM的頁表計算出相應的物理地址,同時,該物理地址被存放在一個TLB表項(TLB Entry)中,以便以後對同一線性地址的引用可以快速地轉換。

最後更新:2017-04-03 05:39:30

  上一篇:go Cocos2d-x中觸摸事件
  下一篇:go C# Timer 定時器應用