加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux-kernel – 将mmap内核引导参数保留的映射内存映射到用户空

发布时间:2020-12-14 02:10:50 所属栏目:Linux 来源:网络整理
导读:正如在 this问题中讨论的那样,我使用内核启动参数memmap = 8G $64G在启动时保留内存块 我编写了一个character driver内核模块,在初始化期间会执行这个保留内存块的ioremap. 正如here所解释的那样,在我的驱动程序mmap中,我需要做的是对ioremap返回的内存块指
正如在 this问题中讨论的那样,我使用内核启动参数memmap = 8G $64G在启动时保留内存块

我编写了一个character driver内核模块,在初始化期间会执行这个保留内存块的ioremap.
正如here所解释的那样,在我的驱动程序mmap中,我需要做的是对ioremap返回的内存块指针的remap_pfn_range.

我在3.0 linux内核上运行它.我的用户空间应用程序打开此内存块作为驱动程序安装的设备.当我从使用空间应用程序执行mmap时,我看到系统挂起.我的dmesg没有提供太多信息.

有什么投入?

static int __init myDev_module_init(void)
{
   int retval;

   myDev_major = register_chrdev(0,DEVICE_NAME,&myDevfops);
   if (myDev_major < 0) 
   {
       err("failed to register device: error %dn",myDev_major);
       retval = myDev_major;
       goto FAILED_CHRDEVREG;
   }

   myDev_class = class_create(THIS_MODULE,CLASS_NAME);
   if (IS_ERR(myDev_class)) 
   {   
       err("failed to register device class '%s'n",CLASS_NAME);
       retval = PTR_ERR(myDev_class);
       goto FAILED_CLASSREG;
   }


   myDev_device = device_create(myDev_class,NULL,MKDEV(myDev_major,0),CLASS_NAME "_" DEVICE_NAME);
   if (IS_ERR(myDev_device)) 
   {
       err("failed to create device '%s_%s'n",CLASS_NAME,DEVICE_NAME);
       retval = PTR_ERR(myDev_device);
       goto FAILED_DEVREG;
   }

这里myDev.startOffset初始化为#defined 64GB,myDev.memSize为8GB.

//myDev.startAddr = ioremap(myDev.startOffset,myDev.memSize);

 //memset_io(myDev.startAddr,myDev.memSize);  
 return 0;

  FAILED_DEVREG:
   class_unregister(myDev_class);
   class_destroy(myDev_class);
  FAILED_CLASSREG:
   unregister_chrdev(myDev_major,DEVICE_NAME);
  FAILED_CHRDEVREG:
   return -1;
}

static int myDev_device_open(struct inode* inode,struct file* filp)
{
    dbg("");

    if ( ((filp->f_flags & O_ACCMODE) == O_WRONLY) || ((filp->f_flags & O_ACCMODE) == O_RDWR) ) 
    {
        warn(" Opening the device with write accessn");
        //return -EACCES;
    }

    info(" device Open is calledn");
    filp->private_data = &myDev;
    return 0;
 }

而mmap非常简单.

?

static int myDev_device_mmap(struct file * f,struct vm_area_struct * vma)
{
 int retval = 0;
struct myDevDev * pDev = (struct myDevDev *)(f->private_data);

dbg("");
if(vma)
{
    if(f)
    {
        if(f->private_data)
            warn("mmap: f->private_data  : %pn",f->private_data);
        else
            warn(" mmap :f->private_data  : NULL n");
    }
    else
    {
        warn("mmap: f  :NULLn");
    }
    warn(": mmap: vm start : %lun",vma->vm_start);
    warn(" mmap: vm end  : %lun",vma->vm_end);
    warn(" mmap: vm pg offset  : %lun",vma->vm_pgoff);



    //retval = remap_pfn_range(vma,vma->vm_start,pDev->startOffset >> PAGE_SHIFT,pDev->memSize,PAGE_SHARED) ;
    // retval = remap_pfn_range(vma,pDev->startAddr >> PAGE_SHIFT,PAGE_SHARED) ;
    //retval = remap_pfn_range(vma,pDev->startAddr,PAGE_SHARED);
    retval = remap_pfn_range(vma,PAGE_SHARED);
    if(retval <0)
    {
        warn(" ERROR : in mapping kernel virtual space to user space return value : %d n",retval);
        return -EINVAL;
    }

    //if(0)
    {
        vma->vm_flags |=VM_LOCKED;
        vma->vm_ops = &myRemapVMOps;
        vma->vm_flags |= VM_RESERVED;

        vma->vm_private_data = f->private_data;
        myDevice_VMA_Open(vma);
    }
}
else
{
    warn ("vma is NULL");
}

dbg(" Done ");
warn("mmpaing done : n");

return 0;
}

从我的用户空间应用程序我正在做以下事情:

?

int err,i=0;
void * mptr = NULL;
printf(" Access the reserved memory chunk n  ");
int fd = open("/dev/myDevice",O_RDWR | O_SYNC);

if(fd <=0)
{
    printf("ERROR: my device driver is not loaded n");
    return 1;
}

  printf("n mmaping mem chunk size :%llu pagesize :%lu input mptr :%pn",sz,getpagesize (),mptr);

  mptr = mmap(0,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_LOCKED,fd,0);

if(mptr == MAP_FAILED) 
{
    close(fd);
    perror("Error mmapping the file");
    printf("nmmapped mem address %pn",mptr);
    exit(1);
}
printf("nmmapped mem address %pn",mptr);

//char * ptr = (char *)mptr;
//*ptr = 'a';

//int * pInt =  (int *) (((char *) mptr)+1); 
//for(;i<10000; ++i)
{
  //  pInt[i] = 2*i;
}

 /* free the mmapped memory
 */
if (munmap(mptr,sz) == -1) 
{
    perror("Error un-mmapping the file");
}

close(fd);

观察:

我没有看到尺寸反映在(vma-> vm_end – vma-> vm_start)中,由于某种原因它始终是4K.

解决方法

>您可以逐步使用标准的phram驱动程序从用户空间访问您的内存.不需要编码.内核重新??编译最多. >你真的有超过64Gb的RAM吗?你的硬件真的支持吗?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读