在尝试从我的内核模块访问共享内存时,为什么会出现“未处理的错误:不精确的外部中止”?

时间:2012-08-08 13:22:33

标签: c linux linux-kernel kernel embedded-linux

我在内核模块中有这个:

/*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 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分: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 

答案 2 :(得分:0)

您的数组是一个char数组,但您的用户空间程序正在以int。

数组的形式访问它

答案 3 :(得分:0)

有关如何正确共享内核和用户空间之间数据的指南,请参阅Implementing mmap for transferring data from user space to kernel space。我已经在我的自定义驱动程序中实现它,它工作正常。如果你不需要速度,使用copy_to_user更安全,更容易。