微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

mmap内核中多个缓冲区崩溃了,请帮忙使用dma_mmap_coherent

如何解决mmap内核中多个缓冲区崩溃了,请帮忙使用dma_mmap_coherent

我正在开发一个Linux内核模块,该模块为每个char设备分配多个缓冲区,然后用户空间应用程序将这些缓冲区映射到用户空间。我的角色设备类具有大约十个或更多的缓冲区,并且在开放时间我分配的缓冲区大小分别为0x8000。我遇到的问题是将这些缓冲区映射到用户空间指针时。我只能映射一个缓冲区,但是当我尝试分配第二个缓冲区时,它就会崩溃。我对 dma_mmap_coherent 不太熟悉,有人可以帮我解决这个问题。

以下是一些代码信息:

//我的内存类型结构

typedef struct
{
    unsigned int *  uaddr;
    unsigned int *  kaddr;
    unsigned long   paddr;
    unsigned int    size;
    unsigned int    index;
    dma_addr_t      handle;
}memory_handle_t

//内核中的缓冲区分配(IOCTL调用

static int allocate__memory_ioctl(struct file *pfile,void __user *uaddr)
{
    struct myClass *my_class = (struct my_class *)pfile->private_data;
    memory_handle_t  minfo;
    int idx = -1;

    if ((idx = find_handle(my_class,NULL)) == -1) {
        printk(KERN_INFO "cannot find a free slot.\n");
        return -EACCES;
    }

    if (copy_from_user(&minfo,uaddr,sizeof(memory_handle_t))) {
        printk(KERN_INFO "CANNOT copY FROM USER POINTER. \n");
        return -EACCES;
    }

    my_class->_memory[idx].size   = minfo.size;
    my_class->_memory[idx].kaddr  = minfo.kaddr = dma_alloc_coherent(my_class->dma_device_p,my_class->_memory[idx].size,&my_class->_memory[idx].handle,GFP_KERNEL);

    if (my_class->_memory[idx].kaddr == NULL) {
        printk(KERN_INFO "Dma memory allocation Failed!\n");
        my_class->_memory[idx].size = 0;
        my_class->_memory[idx].kaddr = NULL;
        return -1;
    } else {
        my_class->_memory[idx].paddr = minfo.paddr = virt_to_phys(my_class->_memory[idx].kaddr);
    }

    minfo.index = idx; /* Pass the index to user so he can use it to map */

    if (copy_to_user(uaddr,&minfo,sizeof(memory_handle_t))) {
        printk(KERN_INFO "CANNOT copY TO THE USER POINTER. \n");
        return -EFAULT;
    }

    return 0;
}

// MMAP

    #define DMA_MAPPING (1 << 7)
    static int c_mmap(struct file *pfile,struct vm_area_struct *vma)
        {
            struct myClass *my_class= (struct myClass *)pfile->private_data;
        
            unsigned int idx = (vma->vm_pgoff & ~DMA_MAPPING) & 0xff; /* We are using the offset for index! */
        
            if ((vma->vm_end - vma->vm_start) > my_class->_memory[idx].size) {
                printk(KERN_ALERT "MMAP Failed,SIZE MISMATCH. \n");
                return -EINVAL;
            }
        
            vma->vm_flags    |= VM_IO;
            vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
        
            return dma_mmap_coherent(my_class->dma_device_p,vma,my_class->_memory[idx].kaddr,my_class->_memory[idx].handle,my_class->_memory[idx].size);
        
        }

// USER-SPACE应用程序

    _fd = open(dev_name.c_str(),O_RDWR);
    if (_fd < 1) {
            printf("Unable to open device file");
            exit(EXIT_FAILURE);
        }

// start allocation and mmap

    size_t     _page_sz = sysconf(_SC_PAGESIZE);
        unsigned int size = TEST_SIZE;
    
        for(int idx=0;idx<11;idx++){
            dma_memory_handle_t dh;
            _mems[idx].size = dh.size = size;
    
            int ret = ioctl(_fd,IOCTL_ALLOC_DMA_MEMORY,&dh);
    
            if  (ret < 0)
            {
                std::cerr << "memory allocation Failed!";
                perror("memory allocation Failed! ");
                throw(std::exception());
            }
    
            int index =  dh.index;
    // fails after the first iteration
            **unsigned int *addr = (unsigned int *) mmap(0,size,PROT_READ | PROT_WRITE,MAP_SHARED,_fd,index*_page_sz);**
    
            if (addr == MAP_Failed)
            {
                std::cerr << "memory map Failed!";
                perror("memory map Failed! ");
                throw(std::exception());
            }
    
            _mems[idx].uaddr   = addr;
            _mems[idx].index   = dh.index;
            _mems[idx].paddr   = dh.paddr;
            _mems[idx].kaddr   = dh.kaddr;
        }

解决方法

谢谢,我能够在指示缓冲区的索引后清除 vma-> vm_pgoff 来解决此问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。