Linux系統中ARM體系的記憶體分頁認識

來源:互聯網
上載者:User

RK28平台Linux系統中ARM體系的記憶體分頁認識

關鍵字

 

 

ARM,記憶體管理,分頁,MMU,虛擬位址

 

 

 

 

Linux系統下ARM晶片記憶體分頁

的一個認知文檔,

閱讀本文前認為讀者瞭解MMU

 

目 錄

1. 概述... 5

2. LINUX的記憶體分頁管理... 5

3. ARM的分頁模式... 5

4. 記憶體分頁相關的資料結構... 5

5. 重要的系統函數調用... 5

6.實體記憶體的定製... 5

7.虛擬空間到物理空間的映射... 5

8.幾個相關問題的討論... 5

一. 概述

記憶體管理是Linux系統的一個極其重要部分,涉及到虛擬-物理地址映射和定址,記憶體分頁,記憶體換頁,核心和使用者進程的記憶體配置,記憶體檔案系統等許多內容,本文僅對Linux系統ARM體繫結構的記憶體分頁,映射定址的認識作一個描述。

二.Linux支援的分頁管理

為支援多種平台處理器的虛擬記憶體管理,Linux(2.6.1)版本以後採用了4級分頁虛擬位址映射(此版本前採用3級分頁映射)的模式,可滿足64位CPU的定址要求。不過,ARM9的MMU只支援兩級頁表地址轉換,且兩級能滿足32位CPU的儲存管理需求,因此ARM體系只使用linux四級中的兩級分頁。Linux四級分頁模式如:

第一級:

全域頁目錄表——對應於代碼中的PGD (見代碼pgtable.h),系統運行時這個頁表的首地址存放於ARM副處理器CP15的寄存器C2中,C2寄存器是和堆棧指標SP,程式指標PC同等重要的寄存器,在進行任務(進程)切換時,沒有虛擬記憶體的作業系統只切換SP和PC,有虛擬記憶體的作業系統增加切換C2,即每個進程都有自己的獨立虛擬空間,也就有獨立的全域頁目錄表PGD。

第2、3、4級

這三級行為基本相同,程式中分別縮寫為

PUD——頁上級目錄

PMD——頁中間目錄

PTE——頁表(最末級)

當系統訪問一個32位虛擬位址時,假設cache未命中且TLB(頁地址快表)中未存有這個地址頁的情況下,MMU將全域頁目錄存放PGD的地址讀出來,取虛擬位址的前若干位(32-宏PGDIR_SHIFT)在該表中進行索引,索引到的32位整數即是下一級頁表PUD的首地址,一直索引到最末級頁表PTE,PTE中對應的索引項目內容(32位整數)前若干位為虛擬位址對應的物理頁地址,頁內位移量為虛擬位址的後若干位,這樣即可以得到一個32位的物理地址。

PTE索引項目的後若干位,記錄了本頁的訪問屬性和存取權限,讀寫標誌,訪問標誌等,以便MMU進行控制。

Linux中的宏PAGE_SHIFT, PMD_SHIFT,PUD_SHIFT,PGDIR_SHIFT分別定義了這四級分頁各自佔用的欄位長度。(../arch/arm/include/asm/pgtable.h))

三.ARM9體系MMU支援的分頁模式

ARM儲存體系支援的頁的大小有幾種——1M,64KB,4KB,1KB,支援的二級頁表大小有兩種:粗粒度和細粒度。在linux中,ARM採用了粗粒度頁表4K頁的模式如,其中一級索引地址有效位為11位,二級索引有效位為9位,頁內位移量為12位:

4KB的頁大小決定了虛擬位址的低12bit留作位移地址用。也決定了二級頁描述符的低12位作為使用者標誌用,4K的頁大小還決定了虛擬位址空間最多可以映射出(4GB/4KB=1024×1024)個頁。程式中下列宏用於定義頁的大小:(arch/arm/include/asm/page.h)

#define PAGE_SHIFT 12

#define PAGE_SIZE (1UL << PAGE_SHIFT)

由上可知二級頁表加頁內位移的總長度為12+9=21,因此程式中定義中間頁表PMD的位元為:(arch/arm/include/asm/pgtable.h)

#define PMD_SHIFT 21

#define PGDIR_SHIFT 21

由各索引表的位元可得到各表的長度:

#define PTRS_PER_PTE 512 表示每個末級頁表PTE中含有512個條目(9bit)

#define PTRS_PER_PMD 1 表示中間頁表PMD表等同於末級頁表PTE

#define PTRS_PER_PGD 2048 表示全域頁目錄表中含有2048個條目(11bit)

因此概括為,ARM體系下實體記憶體和虛擬記憶體按照4KB的大小進行分頁,頁索引表分為兩級,其中全域一級頁表PGD一個,表中含有2048個條目,每個條目對應一個二級頁表物理首地址。二級頁表(PMD或PTE)最多2048個,每個表中含有512個條目,每個條目對應一頁物理首地址。

結合起來,ARM體系在Linux系統下二級分頁可簡要表示如下:

啟動PUD這一級被屏蔽使用,而PMD則等同於PTE為同一個層級,因此ARM在linux下二級分頁為:

虛擬位址——> PGD轉換——> PTE轉換——> 物理地址


四、相關資料結構

1頁描述符,定義在 include/linux/mm_types.h檔案中

struct page {,

}

每個(物理)頁具有一個此類型的資料結構,儲存了該頁的狀態資訊,例如該頁是屬於核心還是使用者,是否空閑,引用計數,是否緩衝等等資訊,該結構佔用32位元組空間,核心通過這個結構掌握一個頁的資訊。有多少個頁,就有多少個頁描述符,頁描述符統一由核心儲存在mem_map數組中。需要佔用整個實體記憶體的1/128

2頁表項,頁中間目錄項,頁上級目錄項和頁全域目錄項的資料結構均為32bit整數:

typedef struct { unsigned long pte; } pte_t; ——頁表項的類型

typedef struct { unsigned long pmd; } pmd_t; ——頁中間目錄項類型

typedef struct { unsigned long pgd[2]; } pgd_t; ——頁全域目錄項類型

3進程描述符task_struct中的mm_struct(include/linux/sched.h),這個結構負責描述進程的儲存分配,一片被進程式控制制的連續線性稱為一個VMA(vm_area_struct),進程的線性空間中由多個VMA鏈表串連而成。

五、記憶體相關的重要的調用

pgd_alloc 分配一個新的全域頁目錄表,通常用在進程初始化階段

brk ——調節進程的動態資料段大小。

_get_free_pages 獲得連續的頁

_alloc_pages 獲得連續的頁

kmalloc 從slab cache分配空間且其實體記憶體為連續的

vmalloc 在虛存區分配空間其虛擬記憶體連續,但實體記憶體不一定連續

shmget 分配共用儲存區,用於進程間共用

mmap ,munmap 將一個檔案對應到記憶體

六、實體記憶體的定義

Linux系統只需要給出實體記憶體的首地址和大小,即可定義實體記憶體給核心使用,相關宏位於/arch/arm/include/asm/memory.h中的

定義實體記憶體首地址:

#define PHYS_OFFSET (CONFIG_DRAM_BASE)

定義實體記憶體末地址:

#define END_MEM (CONFIG_DRAM_BASE + CONFIG_DRAM_SIZE)

定義物理頁起始地址

#define PAGE_OFFSET (PHYS_OFFSET)

七、從虛擬空間到物理空間的映射

虛擬空間的低3GB部分從0-0XBFFFFFFF的虛擬線性地址,使用者態和核心態都可以定址,這部分也是每個進程的獨立空間。

虛擬空間的高1G部分從0XC0000000到0XFFFFFFFF的虛擬位址,只有核心態的進程才能訪問,這種限制由頁目錄和頁表描述符的許可權標誌位決定,通過MMU自動控制。

從虛擬空間的分布,以及到物理地址的空間映射簡要可見:

高1G的核心空間又分為幾部分:

1、 線性地址映射區kernel logical address:從0xc0開始之後的最大896M空間,當實體記憶體小於896M時等於實體記憶體大小。這部分地區的虛擬位址和物理地址線性映射,虛擬位址和物理地址之間只差一個相同的常數,所有實體記憶體也在這裡納入核心統一管理。通過kmalloc在本地區內申請到的實體記憶體是連續的。

2、 虛擬位址映射區(vmalloc區):這一地區內的虛擬位址是連續的,但對應的物理地址可能是不連續的(分頁),通過vmalloc在此地區內申請到的儲存塊其物理地址可能是不連續的。

3、 高端映射區:當實體記憶體大於896M時,超出的實體記憶體部分無法由核心直接定址,通過此段地區間接定址。

低3G的使用者空間主要分為靜態程式碼片段,唯讀資料區段,可寫資料區段,共用庫和動態棧和堆。動態棧(stack)通過其自行向下生長調整,動態堆可通過系統調用brk進行調整,當進程堆不足時,進程向核心申請分配更多的頁進行調整。

綜上所述,從虛擬空間到物理空間的映射存在多種情況,同一個物理頁可能被映射到多個虛擬頁,如:kernel logical地址即上面的線性地址映射區,其映射是線性連續的不交錯,kernel virtual 地址即上面的vmalloc區,其映射到物理空間是交錯的不連續。而使用者進程空間各種資料對應到的物理地址,是交錯的不連續的,且和核心使用的物理地址地區是重疊的。描述了一般的情況:

八、幾個其他和記憶體分頁相關問題的討論:

1、物理空間由誰控制?

物理空間統一由核心控制,在需要時分配給使用者進程。

2、進程間如何隔離?

每個進程有自己的PGD(全域頁目錄表),因此每個進程有自己的空間映射,核心保證各進程映射使用不同的物理空間,從而隔離。

3、如何保證進程不能訪問核心資料?

由頁描述符的許可權標誌位(System/User)控制,聯合ARM9上對應寄存器C1中的S,R位,虛擬位址大於0XC0000000的頁,其頁描述標誌為只能由ARM系統模式訪問。

4、虛擬記憶體到實體記憶體的映射真的能保證系統安全穩定嗎?

主處理器使用的指標全部是虛擬位址,因此主處理器能訪問的資料只能是映射以內的資料,從而保證了運行在主處理器中的使用者任務不會訪問不屬於自己的資料。(基於核心對自己是信任的這個假設)

但主處理器以外的AMBA匯流排-Host裝置除外,例如DMA控制器,其接到匯流排沒有通過MMU,因此使用的還是物理地址。若使用者進程給DMA這種控制器賦予一些非法的物理地址(對主處理器來講是資料),則有可能沖毀實體記憶體的任何地區資料!!!

5、使用者程式為何一般不和linux系統一起編譯?

因使用者程式一般都有新的進程,而進程的建立只能是複製的形式(fork或clone),因為要建立全新進程空間的需要,進程的入口函數只能通過exec啟動一個二進位進程檔案,而不能是一個靜態編譯的目標函數(因為靜態編譯無法使進程的主函數位於另一個獨立的3G進程空間。)因此一般使用者程式和各種庫獨立於linux編譯。此問題我們在其他進程相關的認識文檔中再作進一步討論。

6、應用程式大於實體記憶體時是否可以執行?

可以執行。分頁和換頁的機制使得應用程式不必全部載入到記憶體,而只是載入當前使用的部分頁面到記憶體,從而保證大於物理空間的應用程式能夠運行。只是執行效率問題。

有關儲存管理的其他問題本文暫不討論,有關錯誤和不足望不佞指教。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.