Linux 设备驱动程序 - 将缓冲区从内核映射到另一个模块分配的用户空间



我正在3.4上开发Linux内核驱动程序。此驱动程序的目的是从可能使用 kzalloc() 的其他内核模块中分配的缓冲区向用户空间提供 mmap 接口(下面有更多详细信息)。mmap 提供的指针必须指向此缓冲区的第一个地址。

我从virt_to_phys()中获取物理地址。我在我的 mmap fops 调用中将这个地址右移了 PAGE_SHIFT 到 remap_pfn_range()。

它现在正在工作,但在我看来我没有正确地做这些事情,因为没有什么能确保我的缓冲区在页面顶部(如果我错了,请纠正我)。也许 mmap()ing 不是正确的解决方案?我已经阅读了LDD3的第15章,但也许我错过了一些东西?

详:

缓冲区实际上是由 remoteproc 模块分配的共享内存区域。此区域用于非对称多处理设计 (OMAP4)。由于 rproc_da_to_va() 调用,我可以得到这个缓冲区。这就是为什么没有办法使用 get_free_pages() 之类的东西。

问候

凯文

是的,你是对的:不能保证分配的内存位于页面的开头。没有简单的方法可以保证这一点并使其成为真正的共享内存。

显然,您可以 (a) 将数据从 kzalloc'd 地址复制到新分配的页面,并将其插入到 mmap'ing 进程的虚拟地址空间中,但随后它不会与其他内核模块创建的原始数据共享。

您还可以 (b) 将其他模块分配的实际页面映射到进程的内存映射中,但它不能保证位于页面边界上,并且您还将共享该页面中碰巧驻留的任何其他内核数据(这既是一个安全问题,也是您共享页面的用户空间进程内核数据损坏的潜在来源)。

我想您可以 (c) 修改内存管理器以返回页面开头的每一条分配数据。这将起作用,但是每次驱动程序想要为某些小结构分配 12 字节时,它实际上都会分配 4K 字节(或任何页面大小)。这将浪费大量的内存。

根本没有办法欺骗处理器使内存在页面中显示为两个不同的偏移量。这在物理上是不可能的。

最好的办法可能是 (d) 修改其他驱动程序,以分配您希望以确保页面边界对齐的方式共享的特定数据位(即您编写的内容以替换 kzalloc)。

最新更新