虛擬地址怎樣對映到實體地址
虛擬地址是Windows程式時執行在386保護模式下,這樣程式訪問儲存器所使用的邏輯地址稱為虛擬地址,大家知道嗎?接下來大家跟著小編一起來了解一下虛擬地址對映到實體地址的解決方法吧。
虛擬地址對映到實體地址方法
一般情況下,Linux系統中,程序的4GB記憶體空間被劃分成為兩個部分------使用者空間和核心空間,大小分別為0~3G,3~4G。
使用者程序通常情況下,只能訪問使用者空間的虛擬地址,不能訪問到核心空間。
每個程序的使用者空間都是完全獨立、互不相干的,使用者程序各自有不同的頁表。而核心空間是由核心負責對映,它並不會跟著程序改變,是固定的。核心空間地址有自己對應的頁表,核心的虛擬空間獨立於其他程式。
3~4G之間的核心空間中,從低地址到高地址依次為:實體記憶體對映區—隔離帶—vmalloc虛擬記憶體分配區—隔離帶—高階記憶體對映區—專用頁面對映區—保留區。
【核心空間記憶體動態申請】
主要包括三個函式:kmalloc******, __get_free_pages, vmalloc。
kmalloc******, __get_free_pages申請的記憶體位於實體地址對映區,而且在物理上也是連續的,它們與真實的實體地址只有一個固定的偏移,因此存在較簡單的轉換關係。而vmalloc申請的記憶體位於vmalloc虛擬記憶體分配區***這些區都是以線性地址為度量***,它在虛擬記憶體空間給出一塊連續的記憶體區,實質上,這片連續的虛擬記憶體在實體記憶體中並不一定連續,而vmalloc申請的虛擬記憶體和實體記憶體之間也沒有簡單的換算關係。
因為vmalloc申請的在虛擬記憶體空間連續的記憶體區在實體記憶體中並不一定連續,可以想象為了完成vmalloc,新的頁表需要被建立,因此,知識呼叫vmalloc來分配少量記憶體是不妥的。
一般來講,kmalloc用來分配小於128K的記憶體,而更大的記憶體塊需要用vmalloc來實現。
【虛擬地址與實體地址關係】
對於核心實體記憶體對映區的虛擬記憶體***用kmalloc******, __get_free_pages申請的***,使用virt_to_phys******和phys_to_virt******來實現實體地址和核心虛擬地址之間的互相轉換。它實際上,僅僅做了3G的地址移位。
上述方法適用於常規記憶體***核心實體記憶體對映區***,高階記憶體的虛擬地址與實體地址之間不存在如此簡單的換算關係。因為它涉及到了分離物理頁的頁表控制機制。
【ioremap】
在ARM中,裝置的暫存器或者儲存塊的這部分空間屬於記憶體空間的一部分,我們稱之為IO記憶體。
在核心中訪問IO記憶體之前,我們只有IO記憶體的實體地址,這樣是無法通過軟體直接訪問的,需要首先用ioremap******函式將裝置所處的實體地址對映到核心虛擬地址空間***3GB~4GB***。然後,才能根據對映所得到的核心虛擬地址範圍,通過訪問指令訪問這些IO記憶體資源。
在將I/O記憶體資源的實體地址對映成核心虛地址後,理論上講我們就可以象讀寫RAM那樣直接讀寫I/O記憶體資源了。為了保證驅動程式的跨平臺的可移植性,我們應該使用Linux中特定的函式來訪問I/O記憶體資源,而不應該通過指向核心虛地址的指標來訪問。
【mmap】
用mmap對映一個裝置,意味著使使用者空間的一段地址關聯到裝置記憶體上,這使得只要程式在分配的地址範圍內進行讀取或者寫入,實際上就是對裝置的訪問。這種資料傳輸是直接的,不需要用到核心空間作為資料轉移的中間站。
remap_page_range函式的功能是構造用於對映一段實體地址的新頁表,實現了核心空間與使用者空間的對映。
在核心驅動程式的初始化階段,通過ioremap******將實體地址對映到核心虛擬空間;在驅動程式的mmap系統呼叫中,使用remap_page_range******將該塊ROM對映到使用者虛擬空間。這樣核心空間和使用者空間都能訪問這段被對映後的虛擬地址。
Ioremap:
程序空間ç核心空間çIO記憶體
其中,後面兩個指的是同一段實體記憶體區域,只是一個為虛擬地址,一個為實體地址。程序空間和核心空間對應著不同的實體地址,它們之間的資料傳遞,是實際的資料的拷貝。
Mmap:
程序空間çIO記憶體
其中,程序空間mmap得到的那段虛擬地址跟IO記憶體對應著同一段實體地址。這個過程沒有額外的資料中轉,讀寫都直接針對硬體的實體地址進行。
一般來講,小資料量的傳輸用ioremap******就足夠了,
【IO記憶體的一般訪問方法】
1. 首先是呼叫request_mem_region******申請資源,即告訴核心,本驅動正在使用這段實體記憶體,其他驅動不得訪問它們。在裝置驅動模組載入或open******函式中進行。
2. 接著講暫存器地址通過ioremap******對映到核心空間虛擬地址,之後就可以通過Linux裝置訪問程式設計介面訪問這些裝置的暫存器了。在裝置驅動初始化、write******,read******,ioctl******函式中進行。
3. 訪問完成之後,應對ioremap******申請的虛擬地址進行釋放,並釋放release_mem_region******申請的IO記憶體資源。在裝置驅動模組解除安裝或release******函式中進行。