Linux kernel 将mmap内核引导参数保留的内存映射到用户空间

Linux kernel 将mmap内核引导参数保留的内存映射到用户空间,linux-kernel,kernel,linux-device-driver,embedded-linux,kernel-module,Linux Kernel,Kernel,Linux Device Driver,Embedded Linux,Kernel Module,如前所述,我在引导时使用内核引导参数memmap=8G$64G 我已经编写了一个内核模块,在初始化期间对这个保留内存块进行ioremap。 如前所述,在我的驱动程序mmap中,我需要做的就是为ioremap返回的内存块指针重新映射pfn\u范围 我在3.0Linux内核上运行这个。我的用户空间应用程序将此内存块作为驱动程序安装的设备打开。当我从使用空间应用程序执行mmap时,我看到系统挂起。mydmesg没有向我提供太多信息 有任何输入吗? static int\uu init myDev\u

如前所述,我在引导时使用内核引导参数
memmap=8G$64G

我已经编写了一个内核模块,在初始化期间对这个保留内存块进行ioremap。 如前所述,在我的驱动程序
mmap
中,我需要做的就是为
ioremap
返回的内存块指针重新映射pfn\u范围

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

有任何输入吗?

static int\uu init myDev\u module\u init(void)
{
内部检索;
myDev\u major=register\u chrdev(0、设备名称和myDevfops);
如果(myDev_major<0)
{
错误(“注册设备失败:错误%d\n”,myDev_major);
retval=myDev_major;
后藤失败了;
}
myDev_class=class_create(这个模块,类名);
如果(是错误的(myDev类))
{   
错误(“注册设备类“%s”\n,类名称失败);
retval=PTR_ERR(myDev_类);
转到失败\u CLASSREG;
}
myDev_device=device_create(myDev_class,NULL,MKDEV(myDev_major,0),NULL,class_NAME“u”device_NAME);
如果(是错误(myDev设备))
{
错误(“未能创建设备“%s”\n”、类名称、设备名称);
retval=PTR_ERR(myDev_设备);
后藤失败了;
}
这里,
myDev.startOffset
被初始化为
#define
d64GB,而
myDev.memSize
被初始化为8GB

//myDev.startAddr=ioremap(myDev.startOffset,myDev.memSize);
//memset_io(myDev.startAddr,0,myDev.memSize);
返回0;
失败的\u DEVREG:
类别取消注册(myDev类别);
销毁类(myDev类);
失败的\u CLASSREG:
注销chrdev(myDev专业,设备名称);
失败的\u CHRDEVREG:
返回-1;
}
静态int myDev_device_open(结构索引节点*inode,结构文件*filp)
{
dbg(“”);
如果((filp->f_标志和O_ACCMODE)=O_WRONLY)| |((filp->f_标志和O_ACCMODE)==O_RDWR))
{
警告(“打开具有写访问权限的设备\n”);
//回报-反应;
}
信息(“设备打开被称为\n”);
filp->private_data=&myDev;
返回0;
}
而且
mmap
非常简单

static int-myDev\u-device\u-mmap(结构文件*f,结构虚拟机区域*vma)
{
int-retval=0;
struct mydevdevdev*pDev=(struct mydevdevdev*)(f->private_数据);
dbg(“”);
国际单项体育联合会(vma)
{
如果(f)
{
如果(f->私有数据)
警告(“mmap:f->private\u数据:%p\n”,f->private\u数据);
其他的
警告(“mmap:f->private_data:NULL\n”);
}
其他的
{
警告(“mmap:f:NULL\n”);
}
警告(:mmap:vm启动:%lu\n”,vma->vm\u启动);
警告(“mmap:vm-end:%lu\n”,vma->vm\u-end);
警告(“mmap:vm pg offset:%lu\n”,vma->vm\u pgoff);
//retval=remap\u pfn\u范围(vma,vma->vm\u开始,pDev->startOffset>>页面移位,pDev->memSize,页面共享);
//retval=remap\u pfn\u范围(vma,vma->vm\u开始,pDev->StartADR>>页面移位,pDev->memSize,页面共享);
//retval=remap\u pfn\u范围(vma、pDev->startAddr、pDev->startOffset>>页面移位、pDev->memSize、页面共享);
retval=remap\u pfn\u范围(vma,vma->vm\u开始,pDev->startOffset>>页面移位,pDev->memSize,页面共享);
如果(retval vm_flags |=vm_LOCKED;
vma->vm_ops=&myRemapVMOps;
vma->vm|U标志|=保留vm|U;
vma->vm_private_data=f->private_data;
myDevice_VMA_Open(VMA);
}
}
其他的
{
警告(“vma为空”);
}
dbg(“完成”);
警告(“mmpaing done:\n”);
返回0;
}
在我的用户空间应用程序中,我正在执行以下操作:

int err,i=0;
void*mptr=NULL;
printf(“访问保留内存块\n”);
int fd=open(“/dev/myDevice”,O_RDWR | O_SYNC);
如果(fd
  • 您可以分步骤使用标准phram驱动程序从用户空间访问内存。无需编码。最多可重新编译内核

  • 你真的有超过64Gb的RAM吗?你的硬件真的支持吗

  • 当我从use space应用程序执行mmap时,我看到一个系统挂起

    在使用remap_pfn_range()API之前,请参阅mm/memory.c(内核源代码)中的内联文档,其中指出必须先持有mm信号量

    /**
     * remap_pfn_range - remap kernel memory to userspace
     * @vma: user vma to map to
     * @addr: target user address to start at
     * @pfn: physical address of kernel memory
     * @size: size of map area
     * @prot: page protection flags for this mapping
     *
     *  Note: this is only safe if the mm semaphore is held when called.
     */
    
    如何通过up_read()和down_read()API获取信号量-mm目录中up_read的“grep”就可以了,有很多例子:

    mempolicy.c:    up_read(&mm->mmap_sem);
    migrate.c:  up_read(&mm->mmap_sem);
    mincore.c:      up_read(&current->mm->mmap_sem);
    mmap.c:     up_read(&mm->mmap_sem);
    msync.c:            up_read(&mm->mmap_sem);
    nommu.c:    up_read(&mm->mmap_sem);
    

    通常在调用ioremap()之前,会调用request_mem_region()来声明/保留phys地址空间块。
    /proc/iomem
    会显示什么?如果“系统挂起”(而不仅仅是用户应用程序)那么问题就出在内核中了!
    /proc/iomem
    显示了要保留的块
    100000000-1280000000:reserved
    numactl——硬件
    已经向我显示了内存块没有反映在numa节点中,因此它对内核空间不可见。不确定我们是否还需要执行
    请求_mem_区域()
    /proc/vmallocinfo
    显示了
    ioremap
    内存块!我在设备驱动程序
    init
    中打印了
    ioremap
    返回的地址,它与
    vmallocinfo
    条目匹配!我们支持超过128GB的RAMHm。它感兴趣。您通常使用哪种体系结构?AFAIK Linux不要期望超过64GB的内存。您是否解决了此问题?如果写入到该区域,您可能需要调用up\u write/down\u write。