自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux ARM的存儲分布那些事

存儲 存儲軟件
對于那些支持中斷向量重映射的cpu,該區(qū)域用來撲獲0地址的非法訪問,即null指針。針對arm體系,他是支持中斷向量重映射,該區(qū)域一般保留不用,用來撲獲null指針。

linux arm 內(nèi)存分布總覽

地址范圍大小,虛擬轉(zhuǎn)物理的接口函數(shù),各個區(qū)域?qū)?yīng)的分配函數(shù),該區(qū)域有什么作用,使用場合等等。

首先開始第一個區(qū)域:CPUvector page null pointer trap

該區(qū)域的大小是一個page頁的大小,對于那些不支持中斷向量重映射的cpu,該區(qū)域用來存儲對應(yīng)的中斷向量表;

對于那些支持中斷向量重映射的cpu,該區(qū)域用來撲獲0地址的非法訪問,即null指針。針對arm體系,他是支持中斷向量重映射,該區(qū)域一般保留不用,用來撲獲null指針。

上圖是linux的arm的虛擬地址分布總覽,我們按從低地址到高地址的順序逐個描述,每項的描述包括如下的內(nèi)容的組和:

第二個區(qū)域:應(yīng)用程序地址空間

地址大小范圍屬于[0x1000, 0xbf000000],我知道每個應(yīng)用進(jìn)程都有如下幾個段:text段即存儲代碼段,data段即存儲初始化的數(shù)據(jù)段,bss段即存儲未初始化的數(shù)據(jù)段,堆(malloc,free),棧(往下生長)。他們的地址分布如下:

圖1

在應(yīng)用程序加載到內(nèi)存后,會為每個段,分一個vma的內(nèi)核結(jié)構(gòu)體,并且為每個段都分配了虛擬地址(虛擬地址和大小都存儲在vma結(jié)構(gòu)體中),當(dāng)可執(zhí)行程序的各個段在加載的時候,就會給其分配虛擬地址,每個段對應(yīng)內(nèi)核的一個vma結(jié)構(gòu),程序所有段對應(yīng)的vma,都掛在程序?qū)?yīng)的進(jìn)程的struct mm結(jié)構(gòu)中,但并未給他分配實際的物理地址,待cpu實際去訪問它時,才會去實際建立物理到vma指定的虛擬地址映射,并且將對應(yīng)的段內(nèi)容從elf文件中拷貝到相應(yīng)的物理內(nèi)存中。

譬如當(dāng)cpu要訪問text段時,這個時候并未建立相應(yīng)的映射表,所以會產(chǎn)生page fault異常,從而在異常處理中,linux的內(nèi)存管理系統(tǒng)會為其分配物理內(nèi)存, 并從二進(jìn)制可執(zhí)行程序的elf文件讀取text段到物理內(nèi)存,并且為該進(jìn)程對應(yīng)的頁表建立該物理頁到虛擬地址的映射,這樣cpu就可以訪問該進(jìn)程的text段,并且執(zhí)行對應(yīng)的指令了。

stack跟heap都一樣,在cpu有實際的訪問時,才會分配物理內(nèi)存,并建立物理到對應(yīng)的虛擬地址(在程序加載時,vma中就已經(jīng)分配了虛擬地址)映射。這樣做,就可以節(jié)省程序運(yùn)行時實際物理內(nèi)存的使用。而不是程序一開始就建立了所有物理到虛擬的映射,從而導(dǎo)致物理內(nèi)存被大量不必要的消耗。

第三個區(qū)域:模塊地址

該區(qū)域用來為內(nèi)核模塊分配地址,譬如在insmod一個驅(qū)動模塊時,會通過如下的流程:sysinit_module-->load_module-->layout_and_allocate-->move_module-->module_alloc_update_bounds-->module_alloc來為模塊的各個段分配虛擬地址

圖2

line42可見:就指定了模塊的虛擬地址范圍為:[MODULES_VADDR,MODULES_END] = [0xbf000000,0xbfe00000],總計14MB。注意此時__vmalloc_node_range進(jìn)行了實際的物理內(nèi)存分配,并且建立了物理到虛擬地址的映射。

第四個區(qū)域:PKMAP地址段

該區(qū)域跟fixmap區(qū)域都是用來將高端物理內(nèi)存頁映射到內(nèi)核的線性地址范圍,以使內(nèi)核能夠訪問他。但為什么還要分兩個區(qū)域呢?他們有什么異同?

kmap和fixmap驅(qū)動的地址范圍都是有限的,所以不能長久持有,最好使用完后,就盡快的釋放。

其中kmap區(qū)域的API函數(shù)為:kmap/kunmap,該函數(shù)可以休眠,在地址資源緊張的時候就會發(fā)生休眠。

fixmap區(qū)域的api函數(shù)為:kmap_atomic/__kunmap_atomic,該函數(shù)為每個cpu都保留一個地址槽,并且該函數(shù)是原子的,不會休眠。使用kmap_atomic影射高端物理內(nèi)存頁,處理完后(并且該處理不應(yīng)該休眠,同時kmap_atomic還會禁止搶占),就應(yīng)該盡快調(diào)用__kunmap_atomic進(jìn)行釋放。所以該函數(shù)可以在中斷上下文中使用

kmap地址段的開始虛擬地址和大小在trunk/arch/arm/mm/mmu.c中的kmap_init函數(shù)就指定了。

關(guān)于kmap的詳細(xì)分析,見我的另一篇blog文章。

第五個區(qū)域:內(nèi)核地址空間的直接映射區(qū),即linux內(nèi)核的低端內(nèi)存區(qū)

該區(qū)域也稱為內(nèi)核邏輯地址空間  是指從PAGE_OFFSET(3G)到high_memory之間的線性地址空間,是系統(tǒng)物理內(nèi)存映射區(qū),它映射了全部或部分(如果系統(tǒng)包含高端內(nèi)存)物理內(nèi)存。內(nèi)核邏輯地址空間與系統(tǒng)RAM內(nèi)存物理地址空間是一一對應(yīng)的,內(nèi)核邏輯地址空間中的地址與RAM內(nèi)存物理地址空間中對應(yīng)的地址只差一個固定偏移量(3G),如果RAM內(nèi)存物理地址空間從0x00000000地址編址,那么這個偏移量就是PAGE_OFFSET(0xc0000000)。

系統(tǒng)初始化過程中將低端內(nèi)存永久映射到了內(nèi)核邏輯地址空間,為低端內(nèi)存建立了虛擬映射頁表。低端內(nèi)存內(nèi)物理內(nèi)存的物理地址與線性地址之間的轉(zhuǎn)換可以通過__pa(x)和__va(x)兩個宏來進(jìn)行:

#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) __pa(x)將內(nèi)核邏輯地址空間的地址x轉(zhuǎn)換成對應(yīng)的物理地址,相當(dāng)于__virt_to_phys((unsigned long)(x)),

__va(x)則相反,把低端物理內(nèi)存空間的地址轉(zhuǎn)換成對應(yīng)的內(nèi)核邏輯地址,相當(dāng)于((void *)__phys_to_virt((unsigned long)(x)))

該區(qū)域的內(nèi)存分配函數(shù):kmalloc/kfree和__get_free_page都是從低端內(nèi)存來分配內(nèi)存

第六個區(qū)域:高端內(nèi)存vmalloc區(qū)

該區(qū)域是屬于linux內(nèi)核的高端內(nèi)存地址,該區(qū)域分配的虛擬地址是連續(xù)的,但對應(yīng)的物理地址則可能是不連續(xù)的。該區(qū)域的內(nèi)存分配api函數(shù)為:vmalloc/vfree, 該區(qū)域的api可以用來分配大片內(nèi)存,但對應(yīng)的物理內(nèi)存可能是不連續(xù)的。該函數(shù)會修改頁目錄映射表,因為要為對應(yīng)的虛擬地址和物理地址建立映射關(guān)系。

另外vmalloc區(qū)域跟高端內(nèi)核(high_memory)有一個8MB的保留區(qū)域。端內(nèi)存的物理地址與線性地址之間的轉(zhuǎn)換不能使用上面的__pa(x)和__va(x)宏,關(guān)于該區(qū)域linux內(nèi)核的文檔:arm/memmory.txt有如下的描述:

  1. vmalloc() / ioremap() space
  2. Memory returned by vmalloc/ioremap will 
  3. be dynamically placed in this region. 
  4. Machine specific static mappings are also 
  5. located here through iotable_init(). 
  6. VMALLOC_START is based upon the value 
  7. of the high_memory variable, and VMALLOC_END 
  8. is equal to 0xff000000. 

第七個區(qū)域:DMA內(nèi)存映射區(qū)

該區(qū)域是為DMA分配內(nèi)存的,該段區(qū)域的開始地址和大小在

trunk/arch/arm/mm/dma-mapping.c中已經(jīng)指定了。

分別由consistent_base,DEFAULT_CONSISTENT_DMA_SIZE,

CONSISTENT_END指定該區(qū)域的開始地址,大小,結(jié)束地址。

該區(qū)域的內(nèi)存分配api函數(shù)為:dma_alloc_coherent/dma_free_coherent,

該分配函數(shù)會建立映射表,并且分配出來的物理地址是連續(xù)的。

dma_alloc_coherent的核心函數(shù)為:__dma_alloc。具體詳細(xì)的流程,

請見我的另外一篇blog。在調(diào)用這個api進(jìn)行dma內(nèi)存分配時,

虛擬地址是從CONSISTENT_END高地址往consistent_base低地址方向分配的,

即第一次dma_alloc_coherent調(diào)用的返回值>第二次dma_alloc_coherent

調(diào)用的返回值。請看圖3一個實際的系統(tǒng)dma分配的內(nèi)存情況

另外dma分配函數(shù)分配的物理頁是屬于低端內(nèi)存,但他會通過__dma_alloc_remap函數(shù),將該物理頁重新映射到dma所屬的地址范圍。所以同一個物理頁存在兩個虛擬地址映射,因為該物理頁對應(yīng)的低端內(nèi)存地址在內(nèi)核初始化的時候,就已經(jīng)映射建立好了。

第八個區(qū)域:Fixmap映射區(qū)

該區(qū)域的開始地址和大小在trunk/arch/arm/include/asm/fixmap.h文件中指定了,

該區(qū)域的地址范圍:[0xfff00000,0xfffe0000],該區(qū)域是屬于最頂部的pte頁表中

(set_top_pte),他為系統(tǒng)中的每個cpu都保留了16個page頁的虛擬地址。

該區(qū)域有兩個特殊函數(shù):

  1. fix_to_virt/virt_to_fix  
  2. #define __virt_to_fix(x)(((x) - FIXADDR_START) >> PAGE_SHIFT) 

表示虛擬地址相對FIXADDR_START偏移的頁框數(shù),該返回值應(yīng)該屬于

[0,15]之間。

第九個區(qū)域:CPUvector page

該區(qū)域是用來映射cpu的中斷向量表,因為linux arm使用的高端向量,即cpu中斷產(chǎn)生時,pc指針會自動跳轉(zhuǎn)到0xffff0000+4*vector_num的地方。

圖4

line1107分配一個低端的物理內(nèi)存頁框,line1109 early_trap_init將中斷向量表的內(nèi)容拷貝到這個新分配的物理頁框中。

圖5

line1149-1153:將line1107行分配的物理頁映射到虛擬地址0xffff0000,為cpu中斷產(chǎn)生時,做好準(zhǔn)備(對應(yīng)的地址有各自的跳轉(zhuǎn)代碼,來處理各自的中斷異常)。在這里這個物理頁同樣是存在兩個虛擬地址的映射,一個是低端虛擬地址的影射,一個是高端虛擬地址的映射

最后附一個我們實際使用中的contexA9雙核,ram為1GB大小的系統(tǒng)的linux內(nèi)存分布情況圖:

圖6

可以結(jié)合圖1和圖6一起分析來加深對linux的內(nèi)存分布情況的理解,至于圖1是怎么來的,就需要看上面每個段的具體分析。 

責(zé)任編輯:武曉燕 來源: 嵌入式ARM
相關(guān)推薦

2014-06-06 16:08:17

初志科技

2021-07-09 05:49:53

分布式代碼算法

2017-05-15 21:50:54

Linux引號

2021-08-30 12:05:46

Linux字節(jié)對齊代碼

2019-11-19 14:48:00

Kafka文件存儲

2021-08-06 11:50:49

Linux 字節(jié)對齊Linux 系統(tǒng)

2021-08-17 11:45:44

LinuxC語言字節(jié)

2011-09-19 15:40:35

2020-07-29 08:14:59

云計算云遷移IT

2017-11-20 09:00:34

Linux服務(wù)器時間同步

2013-12-12 17:50:36

開源系統(tǒng)Linux

2018-07-05 09:25:07

系統(tǒng)存儲層次

2012-05-31 09:53:38

IT風(fēng)云15年

2011-05-19 16:47:50

軟件測試

2012-05-01 08:06:49

手機(jī)

2024-02-04 17:03:30

2014-07-22 10:42:04

2015-08-20 09:17:36

Java線程池

2021-03-18 16:05:20

SSD存儲故障

2021-08-11 21:46:47

MySQL索引join
點贊
收藏

51CTO技術(shù)棧公眾號