linux mmap映射内存问题
有一个项目需要将寄存器地址映射到用户态,由用户态对寄存器进行配置,决定使用mmap来进行映射。
我先写了一个驱动和一个用户态程序来验证mmap是否可行。
驱动程序添加了一个misc-device,并申请了一段内存,并将这段内存映射给用户态程序,并将该mmap函数挂给misc设备的file_operations。
int cdma_mmap(struct file *file, struct vm_area_struct *vma)
{
printk("%s %d\r\n", __FUNCTION__, __LINE__);
vma->vm_flags |= VM_READ | VM_WRITE;
if(remap_pfn_range(vma, vma->vm_start, virt_to_phys(global_mem) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, PAGE_COPY))
return -EAGAIN;
return 0;
}
static struct file_operations oper =
{
.owner = THIS_MODULE,
.open = cdma_open,
.read = cdma_read,
.write = cmda_write,
.release = cdma_release,
.unlocked_ioctl = cdma_unlocked_ioctl,
.mmap = cdma_mmap,
};
struct miscdevice cdma_dev =
{
.module = THIS_MODULE,
.name = "XilinxCdma",
.fops = &oper,
};
用户态程序我首先打开misc设备在/dev目录下的设备节点,然后使用mmap进行映射,然后将映射后的内存进行了输出字符串。
int main(void)
{
int fd = open("/dev/XilinxCdma", O_RDWR);
char *buf;
if(fd < 0)
{
printf("open /dev/XilinxCdma failed, return %d\r\n", fd);
}
printf("%s %d fd:%d\r\n", __FUNCTION__, __LINE__, fd);
buf = mmap(NULL, 1024, PROT_READ, MAP_PRIVATE, fd, 0);
if(buf == MAP_FAILED)
{
printf("mmap failed, return %d", *buf);
close(fd);
return 0;
}
else
{
printf("mmap success\r\n");
}
printf("Mem:\r\n%s\r\n", buf);
munmap(buf, 1024);
close(fd);
return 0;
}
我通过echo 1122345455 > /dev/XilinxCdma对该块内存写入数据。
然后执行用户态程序,但是发现映射后的内存没有办法读出我写入的数据,感觉应该是映射返回的地址不对造成的。
问题来了:
1、内核态驱动程序在mmap的时候,为啥将内核态的虚拟地址转换成物理地址后,还需要右移>>PAGE_SHIFT?是因为映射必须以page的方式映射吗?
2、如果是以当前内存所在的page进行映射,这样我实际的内存地址会有偏差,我用户态程序mmap后,如何获得我内核态内存的地址呢?
我先写了一个驱动和一个用户态程序来验证mmap是否可行。
驱动程序添加了一个misc-device,并申请了一段内存,并将这段内存映射给用户态程序,并将该mmap函数挂给misc设备的file_operations。
int cdma_mmap(struct file *file, struct vm_area_struct *vma)
{
printk("%s %d\r\n", __FUNCTION__, __LINE__);
vma->vm_flags |= VM_READ | VM_WRITE;
if(remap_pfn_range(vma, vma->vm_start, virt_to_phys(global_mem) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, PAGE_COPY))
return -EAGAIN;
return 0;
}
static struct file_operations oper =
{
.owner = THIS_MODULE,
.open = cdma_open,
.read = cdma_read,
.write = cmda_write,
.release = cdma_release,
.unlocked_ioctl = cdma_unlocked_ioctl,
.mmap = cdma_mmap,
};
struct miscdevice cdma_dev =
{
.module = THIS_MODULE,
.name = "XilinxCdma",
.fops = &oper,
};
用户态程序我首先打开misc设备在/dev目录下的设备节点,然后使用mmap进行映射,然后将映射后的内存进行了输出字符串。
int main(void)
{
int fd = open("/dev/XilinxCdma", O_RDWR);
char *buf;
if(fd < 0)
{
printf("open /dev/XilinxCdma failed, return %d\r\n", fd);
}
printf("%s %d fd:%d\r\n", __FUNCTION__, __LINE__, fd);
buf = mmap(NULL, 1024, PROT_READ, MAP_PRIVATE, fd, 0);
if(buf == MAP_FAILED)
{
printf("mmap failed, return %d", *buf);
close(fd);
return 0;
}
else
{
printf("mmap success\r\n");
}
printf("Mem:\r\n%s\r\n", buf);
munmap(buf, 1024);
close(fd);
return 0;
}
我通过echo 1122345455 > /dev/XilinxCdma对该块内存写入数据。
然后执行用户态程序,但是发现映射后的内存没有办法读出我写入的数据,感觉应该是映射返回的地址不对造成的。
问题来了:
1、内核态驱动程序在mmap的时候,为啥将内核态的虚拟地址转换成物理地址后,还需要右移>>PAGE_SHIFT?是因为映射必须以page的方式映射吗?
2、如果是以当前内存所在的page进行映射,这样我实际的内存地址会有偏差,我用户态程序mmap后,如何获得我内核态内存的地址呢?
...全文
相关推荐
Linux下得mmap内存映射机制分析
mmap内存映射机制分析
Linux中基于mmap()的共享存储实现研究.pdf
Linux中基于mmap()的共享存储实现研究.pdf
mmap全面解析[项目源码]
本文全面解析了Linux系统调用mmap的原理、用法与实战应用。mmap(内存映射)是一种高效的文件操作、进程间通信和内存管理工具,能够将文件或设备内容映射到进程的虚拟内存空间,使文件操作变得像操作内存一样简单。文章详细介绍了mmap的核心原理、基本用法、典型实战代码(包括文件映射、匿名内存分配和物理内存/设备寄存器映射),并解答了常见问题,如mmap分配的空间类型、效率高的原因、共享内存的实现方式等。此外,还提供了使用mmap的注意事项,如同步问题、多进程同步、大块内存分配、安全性和跨平台兼容性。最后,文章建议开发者关注同步、权限、异常处理等细节,避免越界和资源泄漏问题,并推荐了一些练习项目。
linux-mmap-drviercode-usertestcode
linux mmap 驱动实现,用户空间测试代码 kernel层创建设备节点供用户空间使用,代码实现用户空间通过mmap传递数据到kernel层
内存映射技术在Linux驱动程序中的应用和实现.pdf
内存映射技术在Linux驱动程序中的应用和实现.pdf


驱动程序开发区
