2014-01-14 43 views
3

我執行它經常(使用__get_free_pages())流數據到我在內核分配一個環形緩衝區數據採集設備的Linux設備驅動程序。循環緩衝區(由PCIe硬件寫入)駐留在RAM中,並且我希望用戶空間能夠mmap()RAM區域,以便用戶空間可以讀取其內容。Linux驅動程序:mmap()的內核緩衝區用戶空間,而無需使用的nopage

根據LDD3:

remap_pfn_range的一個有趣的侷限性在於它僅僅給出了上面的物理內存頂部保留頁面地址和物理地址的訪問。 ... 因此,remap_pfn_range不會讓你重新映射傳統地址,其中包括您獲得那些通過調用get_free_page。 ... 映射真實內存到用戶空間的方法是使用vm_ops->nopage處理一次頁面錯誤之一。

在我的情況,我知道需要什麼地址映射到了此刻mmap()緩衝區的全部給定的VMA位置被調用,那麼爲什麼我必須使用斷層的nopage()方法在訪問時一頁一頁地顯示

爲什麼我不能只是設置我的VMA讓我環形緩衝區的全部立即映射到用戶的地址空間?有沒有辦法做到這一點?

我也希望用戶空間程序能順序訪問我的緩衝區,導致在每次跨越頁面邊界時調用nopage()函數時性能降低。 這是否會在實踐中造成相當大的性能下降?(我的緩衝區大,說16 MB)。

(值得注意的是,我用在我以前的設備驅動程序的一個從__get_free_pages()返回的內存remap_pfn_range()和從未有過的任何問題,但我可能只是得到了幸運的。該系統)

+0

我很困惑。您是否問過如何使用'mmap()'從設備*讀*來如何使用它來將您的驅動程序收集到的數據寫入環形緩衝區,以便用戶空間代碼可以訪問它? –

+0

@AaronDigulla:好點。我編輯了這個問題來澄清。謝謝。 – jeremytrimble

+0

@ BenVoigt:雖然這個問題是相關的,但並不是這個問題的重複。 – jeremytrimble

回答

3

一個進一步的研究之後,它看起來像LDD3的說法已經過時了,因爲每一個(稍新一些的)LWN:

TL; DR:在過去,司機可能有手動對kmalloc()/__get_free_pages()分配的頁面設置PG_reserved,然後用於remap_pfn_range()但現在司機現在應該使用vm_insert_page()做等價的東西。

vm_insert_page()顯然只適用於order-0(單頁)分配,所以如果你想分配N個頁面,你必須調用vm_insert_page() N次。

這種用法的例子可以在FireWire驅動程序可以看出:drivers/firewire/core-iso.c

注意頁面是如何單被反覆調用fw_iso_buffer_alloc()alloc_page()分配,並且這些頁面在反覆調用vm_insert_page()後映射到用戶空間VMA fw_iso_buffer_map_vma()。(fw_iso_buffer_map_vma()由中的mmap處理程序調用。)

+0

不知道「PG_reserved」。然而,如果你有'vm_area_struct'並在'vm_flags'中設置'VM_RESERVED',你可以調用'remap_pfn_range'並鎖定頁面。例如,有幾種方法可以首先獲取內存:'pci_alloc_consistent'>'virt_to_phys'>設置'VM_RESERVED'>'remap_pfn_range'。 – EML

相關問題