首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MMAP故障超过4k大小。

MMAP故障超过4k大小。
EN

Stack Overflow用户
提问于 2013-01-28 13:37:22
回答 1查看 1.1K关注 0票数 4

这是我的第一篇帖子,如果有任何错误请告诉我。

我的目标是获得大约150 150MBytes的数据传输从内核到用户空间。这是因为我正在OMAP l138上为DMA设备构建一个驱动程序,以便在DMA设备和FPGA之间传输和接收数据。

  1. 现在在LINUX内核中,我使用dma_alloc_coherent分配可变大小的缓冲区。
  2. 然后,我要传递给用户空间的这个缓冲区的物理地址作为偏移参数,用于从用户空间调用mmap。
  3. 然后从数据复制并从用户空间读取到内核。

此逻辑工作良好,直到缓冲区大小为4096。在4k以上mmap失败并返回"MAP_FAILED“

代码语言:javascript
运行
复制
static int driver_mmap(struct file *f, struct vm_area_struct *vma)
{

    u32bit ret;
    u32bit size = (vma->vm_end)-(vma->vm_start);

    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

    if (size > (NUM_PAGE*PAGE_SIZE)){
        return(-1);  
    }

    if ((ret = remap_pfn_range(vma,vma->vm_start,
                    (virt_to_phys((void *)krnl_area) >> PAGE_SHIFT),
                    size,vma->vm_page_prot)) < 0)
    {
        return ret;  
    }
    printk("\nDVR:The MMAP returned %x to USER SAPCE \n",ret);
    return 0;  

}


//MMAP STEP 1
dmasrc_ptr = dma_alloc_coherent( NULL ,GLOBAL_BUFFER_SIZE , &dmasrc ,0);
if( !dmasrc_ptr ) {
    printk(KERN_INFO "DMA_ALLOC_FAILED for the source buffer ...\n");
    return -ENOMEM;
}else{
    printk( "\n--->The address of SRC is %x..\n",dmasrc_ptr);       
}

temp_source=dmasrc_ptr;



//MMAP STEP 2
// Round the allocated KERNEL MEMORY to the page bondary   
krnl_area=(int *)((((unsigned long)dmasrc_ptr) + PAGE_SIZE - 1)&PAGE_MASK); 
printk(KERN_CRIT "DVR:The KERNEL VIRTUAL ADDRS is %x..\n",krnl_area);

//MMAP STEP 3
// Marking the PAGES as RESERVED 
for (i = 0; i < (NUM_PAGE * PAGE_SIZE); i+= PAGE_SIZE) {  
    SetPageReserved(virt_to_page(((unsigned long)krnl_area) + i)); 


//Application code part

while(1){

    fflush(stdin);
    fflush(stdout);

    printf("\n\n\n----------------------------------------------------\n");
    printf("USR:Please enter your requirement ");
    printf("\n----------------------------------------------------\n");
    printf("\t1----->GET_UPP_OFFSET\n");
    printf("\t2----->UPP_MMAP_CALL\n");
    printf("\t3----->IOCTL_UPP_WRITE\n");
    printf("\t4----->IOCTL_UPP_READ\n");

    printf("\n");
    scanf("%d",&option);
    printf("\nThe OPTION is %d..\n",option);
    printf("\n");

    switch(option){

    case 1 :
    {
        offset=0;
        ret = ioctl(dev_FD ,IOCTL_UPP_START, &info);
        if (ret < 0) {
            printf("dma buffer info ioctl failed\n");
        }       
        offset = info.var;      
        printf("THE ADDRESS WE GOT IS %X..\n",offset);

    }
    break;

    case 2 :
    {
        printf("THE OFFSET is %X..\n",offset);
        mmap_Ptr= mmap(0,BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, dev_FD, 0);     
        if (mmap_Ptr == MAP_FAILED){
            printf("USR[UPP] :MMAP FAiled \n\n");
            close(dev_FD);
            exit(-1);   
        }
        printf("THE MMAP address is %X..\n",mmap_Ptr);

    }
    break;

    case 3:
    {
        struct upp_struct user_local_struct;

        printf("\n***************************************************\n");
        for (i = 0; i <(1024);i++) {  
            *(mmap_Ptr+i)=test_var;
            printf("WR:%X ",*(mmap_Ptr+i));
            //test_var++; 
        } 
        ioctl(dev_FD , IOCTL_UPP_WRITE ,&user_local_struct);    

        printf("\n***************************************************\n\n\n");
        for(i=0;i<20402;i++){
            //NOP
        }

        //test_var=0x00;
    }
    break;

    case 4:
    {
        struct upp_struct user_local_struct;
        ioctl(dev_FD , IOCTL_UPP_READ,&user_local_struct);

        for(i=0;i<20402;i++){
            //NOP
        }
        printf("\n***************************************************\n");
        for (i = 0; i <(1024);i++) {  
            printf("RD:%X",*(mmap_Ptr+i));  
        }
        printf("\n***************************************************\n\n\n");  
    }
    break;

    default:
    { 
        printf("USR:You have entered an wrong option \n");
        printf("\nUSR:CLosing the FILE ENTERIES ...\n");
        munmap(mmap_Ptr,BUFFER_SIZE);
        free(source_ptr);
        free(dest_ptr);
        close(dev_FD);
        exit(0);
    }
    break;

} //END OF SWITCH LOOP  

} //END OF WHILE LOOP
EN

回答 1

Stack Overflow用户

发布于 2014-03-17 04:49:42

使用get_free_pages分配多个页面,或者使用vmalloc,但是您需要在每个页面上调用remap_pfn_range,因为vmalloc编辑的物理内存可能物理上不连续。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14563264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档