1

我在内核模块中有这个:

/*global scope declared*/ 
static int array[10]={1,2,3,4,5,6,7,8,9,10};

而且我有完美的打开关闭读写功能,我想array[8]与此页面底部的用户空间应用程序共享。

在内核模块中:

static int *my_mmap (struct file *filep, struct vm_area_struct *vma ) {

    if (remap_pfn_range(vma,
                vma->vm_start,
                virt_to_phys(array)>> PAGE_SHIFT,
                10,
                vma->vm_page_prot) < 0) {
        printk("remap_pfn_range failed\n");
        return -EIO;
    }


    return 0;

用户空间源代码中的应用程序:

#define LEN (64*1024)
/* prototype for thread routine */

#define FILE_PATH "/dev/my_module"


int main() 
{
    int i=0;
    int fd = open(FILE_PATH,O_RDWR);    
    int* vadr = mmap(0, LEN, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

    for (i=0;i<10;++i){

        printf("%d",*(vadr+i));
    }

    return 0;
}
4

4 回答 4

1

这在很多层面上都是错误的,我什至不知道从哪里开始:-)

  1. virt_to_phys 可能实际上不适用于 vmalloc 分配的内存,这是 Linux 在大多数平台上用于动态模块数据部分的内容。
  2. 即使是这样,数据在物理内存中也可能根本不连续。
  3. 数组可能未在页面边界上对齐。
  4. 您的数据结构是 40 字节,您正在映射 10 页随机内核内存。
  5. 如果处理器具有虚拟索引、物理标记 (VIPT) 缓存,当有多个虚拟映射到同一物理地址时,您可能会遇到缓存一致性问题。

可能还有更多问题,但这就是我想到的。

正确的做法不是在内核空间和用户空间之间共享数据,而是使用 copy_to_user 和朋友将其复制过来,除非您真的知道自己在做什么以及为什么。

如果你真的必须共享内存,那么分配一个空闲页面,从内核空间(例如kmap)和用户空间(就像你所做的那样)映射它,并希望你的平台没有VIPT缓存。

于 2012-08-09T08:28:04.473 回答
0

我是内核编程的新手,所以我可能会遗漏一些东西,但在这种情况下你不能使用 copy_to_user 吗?

    unsigned long copy_to_user(void __user * to, const void * from, unsigned long n); 

简单来说

to = address in userspace (destination)
from = address in kernel (source)
n = number of bytes to copy 
于 2012-08-08T20:01:06.823 回答
0

您的数组是一个 char 数组,但您的用户空间程序将它作为一个 int 数组访问。

于 2012-08-09T03:51:03.737 回答
0

有关如何在内核和用户空间之间正确共享数据的指南,请参阅实现 mmap 以将数据从用户空间传输到内核空间。我在我的自定义驱动程序中实现了它,它工作正常。但是,如果您不需要速度,则使用 copy_to_user 更安全、更容易。

于 2017-06-16T21:52:16.140 回答