關於驅動開發中mmap函式的實現

2021-06-20 06:04:33 字數 1515 閱讀 8887

關於驅動開發中mmap函式的實現

在編寫裝置驅動程式的時候,如果要想把裝置記憶體對映到使用者空間,那需要我們實現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可以對多個連續的物理頁面進行處理。remap_pfn_range 通過你的頁幀號來建立頁表, 並對映到使用者空間!

一般情況是你的驅動分配一塊記憶體,然後在驅動的mmap中使用這塊記憶體的實體地址轉成頁幀號, 再呼叫remap_pfn_range!

假設1你是通過kmalloc(),get_free_pages()等分配的,這種記憶體頁是不能通過remap_pfn_range()對映出去的,要對每個頁面呼叫setpagereserverd()標記為"保留"才可以,virt_to_phys()函式只是得到其實體地址,remap_pfn_range()中的第三個引數是要求物理頁便的"幀"號,即pfn,所以你的phys還要">> page_shift"操作

假設2你是通過vmalloc分配得來的,同上,不同的是要用vmalloc_to_pfn

3,用kmalloc,get_free_pages,vmalloc分配的物理記憶體頁面最好還是不要用remap_pfn_page方法,建議使用vma的nopage方法

4,對於這樣的裝置記憶體,最好對呼叫pgprot_nocached(vma->vm_page_prot)後傳給remap_pfn_range,防止處理器快取

Linux中mmap函式的使用

linux利用mmap函式允許程式建立共享記憶體,建立一段可以被多個程式讀寫的記憶體,乙個程式的修改可以被其他程式看見。還可以用在檔案的處理上,通過帶特殊許可權集的虛擬記憶體段實現,對虛擬記憶體段的讀寫會使作業系統讀寫磁碟檔案中的對應部分。include void mmap void addr,si...

關於測試驅動開發的思考

關於測試驅動開發的思考 測試驅動開發 test driven develop 作為敏捷思想的重要組成部分,將開發和測試在同一時段完成,我認為是乙個很不錯的想法,尤其是經歷了無數測試後的返工以及開發中的疏漏後,測試驅動開發將作為以後開發工作中首當其衝的選擇。據我所知,這裡有幾個誤區需要糾正,其一 敏捷...

關於驅動中的併發

核心程式設計中,我們不能使用使用者態的c庫函式的printf 函式輸出資訊,而只能使用printk 每個printk都 有個優先順序,核心一共有8個優先順序,預設default message loglevel,如果優先順序數字比int console loglevel變數小的話,訊息就會列印到控制...