提出這個問題是因為32位的x86如果沒有特殊的支援和機制,是無法訪問896m以上的物理記憶體的,這讓我很奇怪。雖然核心所分配到的空間是[3g,4g-1),但是這並不代表核心本身的定址能力是1g呀。
後來看到一篇文章說,linux會在初始化的時候把物理記憶體對映到核心空間。這也讓我很奇怪。linux本身維護了乙個page的陣列來作為物理記憶體的「倉庫」,這個陣列的下標實際上就是物理記憶體的頁面號,linux會在初始化的時候初始化這個陣列。我的理解是,後期的虛存到物理記憶體的對映實際上都落實到了對這個page陣列的操作,這就夠了。為什麼還要把物理記憶體位址對映到核心空間?
並且,為什麼僅僅是896m,剩下的128m核心位址空間去哪兒了?難道剩下的這128m就是核心本身麼?如果是的話,那麼核心中的各種系統呼叫、核心資料結構等就都要擠在這個空間裡,這樣要對這相對所剩無幾的空間進行良好的規劃,而不是像普通程式那樣,一開始就是8開頭的虛存空間位址;如果不是的話,那這128m方的又是什麼東西,核心自己又躲到哪兒去了?
linux這樣做,只是為了簡化核心中虛擬位址和實體地址之間相互轉化的工作,__va()、__pa()輕鬆的就變換過來了,並不是說物理記憶體對映到核心空間就全部被核心佔了。對於核心中非動態資料使用的物理記憶體是不可以變了,但是動態的部分,是可以釋放掉的,而釋放掉後這一部分對應的物理記憶體又可以影射到使用者空間。
至於為什麼不完全對映1g的空間,我想是因為還要留一片核心的虛擬位址給ioram用,比如說pci的ioram,通過ioremap對映總得留下點虛擬位址把,而ioram的虛擬位址又必需在核心空間中,也就是3-4g。
不完全對映1g,是因為要保留出一段空間來供動態對映所使用,比如當記憶體大於1g是,除了前面的890m可以直接對映,後面的空間都需要臨時對映一下,用完解除對映(某些平台下實際解除是個空操作)。
對於剛好1g記憶體的時候,動態對映其實是沒有必要的。www.kerneltrap.org上曾經有文章討論過乙個patch,可以去掉動態對映,但只能用於少於1g的情況,好像現在kernel的配置已經有這個選項了。
核心的位址是從物理記憶體的0位址開始的,而0xc0000000就是這個偏移量
"linux這樣做,只是為了簡化核心中虛擬位址和實體地址之間相互轉化的工作,__va(), __pa()輕鬆的就變換過來了。 "
實體地址 <--> 虛擬位址
#define __pa(x) ((unsigned long)(x) & 0x3fffffff)
#define __va(x) ((void *)((unsigned long)(x) | 0xc0000000))
GPU 共享記憶體位址對映方式
當乙個warp中的不同執行緒訪問乙個bank中的不同的字位址時,就會發生bank衝突。如果沒有bank衝突的話,共享記憶體的訪存速度將會非常的快,大約比全域性記憶體的訪問延遲低100多倍,但是速度沒有暫存器快。然而,如果在使用共享記憶體時發生了bank衝突的話,效能將會降低很多很多。在最壞的情況下,...
S5PV210的記憶體位址對映詳解
s5pv 210 屬於 arm cortex a8架構,32 位cpu cpu 設計時就有 32 根 位址線 32 根 資料線 32 位址線 決定了 cpu 位址空間 為 4g 2 32 次方 sfrs 256m 位址 dram1 記憶體第乙個插槽 1g 外界記憶體 dram2 512m 記憶體 1...
記憶體位址重對映的選項 PE檔案與虛擬記憶體之間的對映
在除錯漏洞時,可能經常需要做這樣兩種操作。1 靜態反彙編工具看到的pe檔案中某條指令的位置是相對於磁碟檔案而言的,即所謂的檔案偏移,我們可能還需要知道這條指令在記憶體中所處的位置,即虛擬記憶體位址 va 2 反之,在除錯時看到的某條指令的位址是虛擬記憶體位址,我們也經常需要回到pe檔案中找到這條指令...