Linux kernel 将缓冲区从内核映射到另一个模块分配的用户空间

Linux kernel 将缓冲区从内核映射到另一个模块分配的用户空间,linux-kernel,linux-device-driver,shared-memory,mmap,Linux Kernel,Linux Device Driver,Shared Memory,Mmap,我正在3.4上开发一个Linux内核驱动程序。此驱动程序的目的是通过在其他内核模块中分配的缓冲区(可能使用kzalloc())向用户空间提供mmap接口(更多详细信息如下)。mmap提供的指针必须指向此缓冲区的第一个地址 我从virt\u到\u phys()获取物理地址。在我的mmap fops调用中,我将此地址按页次右移到重新映射\u pfn\u range() 它目前正在工作,但在我看来,我没有正确地完成这些工作,因为没有任何东西可以确保我的缓冲区位于页面顶部(如果我错了,请纠正我)。也许m

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

我从virt\u到\u phys()获取物理地址。在我的mmap fops调用中,我将此地址按页次右移到重新映射\u pfn\u range()

它目前正在工作,但在我看来,我没有正确地完成这些工作,因为没有任何东西可以确保我的缓冲区位于页面顶部(如果我错了,请纠正我)。也许mmap()ing不是正确的解决方案?我已经阅读了LDD3的第15章,但也许我遗漏了什么

详情:

缓冲区实际上是由remoteproc模块分配的共享内存区域。该区域用于不对称多处理设计(OMAP4)。由于rproc\u da\u to\u va()调用,我可以获得此缓冲区。这就是为什么没有办法使用像“获取免费页面”()这样的东西

问候


Kev

是的,您是正确的:无法保证分配的内存位于页面的开头。对于你们来说,并没有一个简单的方法来保证这一点,并让它成为真正的共享内存

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

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

我想你可以(c)修改内存管理器,在页面开始时返回分配的每一条数据。这是可行的,但是每次驱动程序想为一些小结构分配12个字节时,实际上就是分配4K字节(或任何页面大小)。这将浪费大量内存

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


您最好的选择可能是(d)修改另一个驱动程序,以分配您希望共享的特定数据位,并确保在页面边界上对齐(即,您编写的用于替换kzalloc的内容)。

非常感谢您的回答。这会让事情变得更清楚。我还想过使用(a)方法从用户()复制\u但是我有大量的内存要传输(图像),所以我担心会失去一些性能。(b)非常适合快速脏的方法,我不会实现它,但是,出于好奇,你知道如何检索页面中数据开始的偏移量吗?(c)似乎也非常脏…(d)是解决我问题的最佳方案,可能会为remoteproc驱动程序带来新功能。再次感谢,至少我学到了一些东西!在页面中查找偏移量很容易:addr&(page_SIZE-1)