Linux驱动程序:不使用nopage将mmap()内核缓冲区映射到用户空间 [英] Linux Driver: mmap() kernel buffer to userspace without using nopage

查看:0
本文介绍了Linux驱动程序:不使用nopage将mmap()内核缓冲区映射到用户空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为一个数据采集设备实现一个Linux设备驱动程序,它不断地将数据流入我在内核中分配的循环缓冲区(使用__get_free_pages())。循环缓冲区(由PCIe硬件写入)驻留在RAM中,我希望用户空间能够mmap()该RAM区域,以便用户空间可以读取其内容。

根据LDD3:

remap_pfn_range的一个有趣的限制是,它只允许访问保留的页和物理内存顶部以上的物理地址。 ..。 因此,REMAP_PFN_RANGE不允许您重新映射常规地址,其中包括通过调用GET_FREE_PAGE获得的地址。 ..。 将实际RAM映射到用户空间的方法是使用vm_ops->nopage一次处理一个页面错误。

在我的例子中,我确切地知道在调用mmap()的时刻需要将哪些地址映射到整个缓冲区的给定VMA位置,那么为什么我必须在访问页面时使用nopage()方法,每次一个页面出错?

为什么我不能直接设置我的VMA,以便将我的整个环形缓冲区立即映射到用户的地址空间?有办法做到这一点吗?

我还预计用户空间程序将按顺序访问我的缓冲区,这会在每次跨越页面边界时调用nopage()函数时导致性能损失。这在实践中是否会对性能造成相当大的影响?(我的缓冲区很大,比如16 MB。)

(值得注意的是,我在以前的一个设备驱动程序中使用过从__get_free_pages()返回的内存中的remap_pfn_range(),从未出现过任何问题,但我可能只是在该系统上走运。)

推荐答案

进一步研究后,根据LWN:

,看起来LDD3的声明已经过时

TL;DR:过去,驱动程序可能会在kmalloc()/__get_free_pages()分配的页面上手动设置PG_reserved,然后使用remap_pfn_range(),但现在驱动程序应该使用vm_insert_page()来执行相同的操作。

vm_insert_page()显然仅适用于0阶(单页)分配,因此如果要分配N个页面,则必须调用vm_insert_page()N次。

在Firewire驱动程序中可以看到这种用法的示例:drivers/firewire/core-iso.c

注意如何通过重复调用fw_iso_buffer_alloc()中的alloc_page()来分配单个页面,然后通过重复调用fw_iso_buffer_map_vma()中的vm_insert_page()将这些页面映射到用户空间VMA中。(fw_iso_Buffer_map_vma()由drivers/firewire/core-cdev.c中的mmap处理程序调用。)

这篇关于Linux驱动程序:不使用nopage将mmap()内核缓冲区映射到用户空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆