在編寫裝置驅動程式的時候,如果要想把裝置記憶體映射到使用者空間,那需要我們實作mmap,通過看ldd3上面的介紹,對實作mmap有了一點了解.
書上介紹主要是利用
int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr,
unsigned long pfn, unsigned long size, pgprot_t prot) 函數或者
int io_remap_page_range(struct vm_area_struct *vma, unsigned long
virt_addr, unsigned long phys_addr, unsigned long size, pgprot_t
prot)函數來實作,它們負責建立新的頁表.這兩個函數的差別是第一個函數是在參數pfn指向實際系統RAM的時候使用,而第二個函數是在phys_addr指向I/O記憶體的時候使用.對于ARM平台來說,系統記憶體和端口應該是統一編址的,是以兩個函數是等價的.
還有另外一個函數就是nopage函數,是VMA結構體中可以填充的一個函數,在虛拟頁沒有所對應的實體頁的時候,會調用此函數,來配置設定一個實體頁給虛拟頁.
int remap_page_range(unsigned long from, unsigned long phys_addr,
unsigned long size, pgprot_t prot)
其中from是映射開始的虛拟位址。這個函數為虛拟位址空間from和from+size之間的範圍構造頁表;
phys_addr是虛拟位址應該映射到的實體位址;
size是被映射區域的大小;
prot是保護标志。
remap_page_range的處理過程是對from到form+size之間的每一個頁面,查找它所在的頁目錄和頁表(
必要時建立頁表),清除頁表項舊的内容,重新填寫它的實體位址與保護域。
remap_page_range可以對多個連續的實體頁面進行處理。<<Linux裝置驅動程式>>指出,
remap_page_range隻能給予對保留的頁和實體記憶體之上的實體位址的通路,當對非保留的頁使用