ARM Linux儲存機制詳解

2021-06-05 13:49:00 字數 3334 閱讀 5124

arm-linux儲存機制詳解

1.記憶體管理和mmu

當arm 要訪問儲存器時,mmu 先查詢tlb(translation lookaside buffer,旁路轉換緩衝)中的虛擬位址表。如果tlb 中沒有虛擬位址的入口,則轉換表遍歷硬體會從存放在記憶體的轉換表中獲得轉換和訪問器許可權。一旦取到,這些資訊將被放到tlb 中,這時訪問儲存器的tlb 入口就拿到了。

在tlb 中其實包含了以下資訊:

1)控制決定是否使用高速緩衝

2)訪問許可權資訊

3)在有cache 的系統中,如果cache 沒有命中,那麼實體地址作為線性獲取(line fetch)硬體的輸入位址。如果命中了cache 那麼資料直接從cache 中得到,實體地址被忽略。

arm 的工作流程可用下圖表示:

這種機制是純粹的高速硬體操作,並不需要作業系統來完成。作業系統只要提供記憶體轉換表就可以了,但是需要符合一定的格式。

arm9 的mmu 對映表分為兩種,一級頁表的變換和二級頁表變換。兩者的不同之處就是實現的變換位址空間大小不同。一級頁表變換支援1 m 大小的儲存空間的對映,而二級可以支援64 kb,4 kb 和1 kb 大小位址空間的對映。在linux 中最終使用了1 m 一級頁表和4 kb 的二級頁表(即 1m段區和4kb頁面)。

核心中位址轉換表建立過程

第一階段是發生在核心解壓縮、自引導時,也就核心映象zimage 的檔案頭部分。相關**從某種意義上來講不屬於核心,它是bsp **中的一部分,是需要根據不同的架構來分別實現的。通過平面對映的方式建立了256m 空間節描述表。但是,這個對映表是臨時的,是為了提高核心解壓縮時的速度而實現的。在解壓縮結束之後,進入核心**之前,mmu 功能就被關閉了,隨之的對映表也被廢棄不用。

當decompress_kernel 函式實現核心的解壓縮之後,那麼核心啟動的第一階段工作就完成了。接下來就準備啟動真正的核心,但是核心啟動時必須要先關閉mmu,以至於剛才的第一階段對映表不能使用了。

第二階段是的頁表建立是非常關鍵的。同樣也是使用組合語言來實現。在**中,有個函式__create_page_tables,這就是建立mmu 對映表,開啟mmu 做準備的重要動作。

這是真正意義上的第一次建立被核心所用的節轉換表,經過上述**實現,所建立的節轉換表對應內容:

初始對映表:

0x10 0000=1m           

上表中黑體字所示比較特殊,這一節空間進行了兩次對映:乙個是和實體地址相同的對映;乙個是對映到0xc000 0000 以上的空間。這是因為按照linux 記憶體空間劃分的慣例,3g(0xc0000000)以上的空間作為核心空間,其他的作為使用者記憶體空間。所以這樣對映後,只要在前1m 的程式之內的空間開啟mmu,並且使用位址跳轉指令就可以使核心跑到0xc0000000 以上的空間執行了。//???????但是這個對映表還不是最終系統使用的對映表。

第三階段是建立更高階別的對映關係和對映方法,主要和架構相關。不同的架構有不同的對映方法,比如arm 就是二級對映的方法實現位址對映,但是必須按照linux 的**對映模型pgd、pmd、pte 來實現。    從核心**上來看,核心啟動的過程中主要有兩個函式比較重要:

(2) start_kernel->setup_arch->paging_init->devicemaps_init

(3) start_kernel->trap_init

函式一:重新建立了一級對映表,新增了對記憶體空間的二級對映,同時建立了bootmem 這個記憶體管理器。

函式三:則是完成了中斷向量的對映。

這樣就完成了關於平台的基本對映。但是,位址對映遠遠沒有結束,驅動需要位址空間對映,使用者程式需要位址空間對映等,這些就靠核心的整個記憶體管理模組來實現了。按照一般的arm 平台的對映習慣最後得到的對映如下:

以上是在核心啟動不同階段的頁表操作過程,到此為止,核心基本完成了對映表的配置。這個對映表不是固定不變的對映表,隨著核心的執行而改變。這樣才能夠實 現作業系統的記憶體管理,埠對映管理功能,比如:相同實體地址的重複對映,外設io 口管理等。好在linux提供進行記憶體管理操作的方法。

附:q1:板載sdram是64m,實體地址是0x3000 0000 - 0x33ff ffff,在初始化mmu頁表時,把sdram的虛擬位址也對映到這個範圍,是為什麼?是不是為了跟沒有mmu下的位址操作變得一樣,也就是方便移植?

a1:和x86相似,核心使用虛擬位址時,由於在使用分頁前後引用的位址都要是在物理記憶體中的同乙個位址(因為連線的時候都是相對乙個 page_offset),而你的page_offset和phys_offset都是0x3000000;所以實體地址和虛擬位址就是同樣的了

在x86上,page_offset是0xc000 0000,所以在沒有分頁的使用引用變數需要使用變數的值-               0xc000 0000,而你的系統上則不需要。就是個對映,能簡單就簡單。

q2:每個程序都有自己的執行空間,意思是不是指有各自的頁表?即mva?

q4:初始化的mmu頁表和程序的虛擬位址mva是什麼關係?是乙個表嗎?arm裡根據不同程序的pid,會重建mva(「轉換後的虛擬位址」),會不會把原來初始化的對應好的那部分頁表內容給覆蓋掉?

a4:核心和程序是兩套頁表。你說的初始化的頁表是核心自己使用的,程序的頁表會在執行程序時(execve)建立,根據可執行檔案的內容,分配相應的物理記憶體(不說延遲分配),然後把程序的頁表更改相應的項,這樣程序就有自己的頁表了。

~~~~~~~

linux的mmu是如何與軟體結合完成記憶體對映的?     

問:linux的記憶體對映是通過mmu硬體完成的,但是我們又知道linux在i386的二級對映中通過 如下三個函式來獲取pgd、pmd和pte的表項的。既然有了這三個函式,那mmu的硬體到底完成了記憶體對映過程中的哪些工作??

#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))

static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)

#define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + __pte_offset(address))

難道是pgd_offset、pmd_t、pte_offset這三個函式的實現依賴於mmu?  

換句話說:linux的mmu是如何與軟體(如上述三個函式)結合完成記憶體對映的?

答:mmu的作用有兩個:位址翻譯和位址保護

軟體的職責是配置頁表,硬體的職責是根據頁表完成位址翻譯和保護工作。

那三個函式是用來訪問頁表的。如果cpu沒有硬體mmu那麼這張表將毫無意義。

你必須從cpu的角度去理解記憶體對映這個概念。記憶體對映不是呼叫乙個函式,然後讀取返回值。而是cpu通過mmu把一條指令中要訪問的位址轉換為實體地址,然後傳送到匯流排上的過程

IPFS儲存機制詳解

ipfs全稱 interplanetary file system,譯星際檔案系統 是乙個旨在建立持久且分布式儲存和共享檔案的網路傳輸協議。該技術是一種內容可定址的對等超 分發協議。它的出現,能讓網際網路的速度便捷 更安全 更開放。其目的在於推翻現有的http協議。我們知道ipfs的儲存機制類似於共...

時鐘 ARM Linux系統的時鐘機制簡單理解

linux下有兩類時鐘 標準計時器,時鐘滴答計時 jiffies 的幾個基本引數 計時器timer晶體振盪器在1秒內產生的時鐘脈衝個數就是時鐘週期的頻率,要注意把這個timer的時鐘週期頻率與時鐘中斷的頻率區別開來,linux用巨集clock tick rate來表示計時器的輸入時鐘脈衝的頻率 比如...

詳解 ARM Linux啟動過程分析 2

origin 呼叫 linux核心映像 bootloader完成的最後一項工作便是呼叫 linux核心。如果 linux 核心存放在 flash 中,並且可直接在上面執行 這裡的 flash 指 nor flash 那麼可直接跳轉到核心中去執行。但由於在 flash 中執行 會有種種限制,而且速度也...