通过mmap将连续物理地址映射到用户空间
2013-12-13 20:40
429 查看
由于MMU对用户空间的内存采用页式管理,用户空间的内存都是虚拟的,只有当真正写入物理内存时,系统才会判断是否为该虚拟内存分配物理内存,如果未分配就会触发缺页中断,然后分配一整页的内存给应用程序。所以用户空间的内存表面上连续,但是实际的物理内存不一定连续。
由于种种原因,我们有时候会需要用户空间的虚拟内存在物理上面也连续。按照MMU的管理方式,虚拟内存最多只能有一页——4096字节在物理上面也是连续的。而这是远远不能满足我们的需求的。
多方查阅资料,发现采用mmap可以达到这个目的。mmap是由内核实现,应用程序通过接口调用而产生一块内核和应用程序都能访问的内存,主要用于显卡驱动。下面介绍一个简单的例子,用于通过mmap为应用程序分配较大的连续物理内存。
kernel部分:主要是创建一个字符设备,配置其mmap函数,分配连续内存。
应用部分:
通过打印信息,可以看到已经获得了连续的物理内存(由内核分配,应用可以使用)。
由于种种原因,我们有时候会需要用户空间的虚拟内存在物理上面也连续。按照MMU的管理方式,虚拟内存最多只能有一页——4096字节在物理上面也是连续的。而这是远远不能满足我们的需求的。
多方查阅资料,发现采用mmap可以达到这个目的。mmap是由内核实现,应用程序通过接口调用而产生一块内核和应用程序都能访问的内存,主要用于显卡驱动。下面介绍一个简单的例子,用于通过mmap为应用程序分配较大的连续物理内存。
kernel部分:主要是创建一个字符设备,配置其mmap函数,分配连续内存。
#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/fcntl.h> #include <linux/vmalloc.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/page.h> #include <linux/mm.h> #include <linux/platform_device.h> #include <linux/device.h> #include <linux/moduleparam.h> #include <linux/cdev.h> #include <linux/slab.h> #define MMAPIOMEM_DEV_NAME "mmapiomem" #define MMAPIOMEM_DEV_MAJOR 280 #define MMAP_BUF_SIZE 0x500 char *mmap_buf_ptr; int mmapiomem_open(struct inode *inode,struct file *filp) { return 0; } int mmapiomem_release(struct inode *inode,struct file *filp) { return 0; } int mmapiomem_mmap(struct file *filp,struct vm_area_struct *vma) { int result; vma->vm_flags|=VM_RESERVED|VM_SHARED; vma->vm_flags|=VM_IO; result=remap_pfn_range(vma, vma->vm_start, ((unsigned int)mmap_buf_ptr)>>PAGE_SHIFT, PAGE_SIZE *4, vma->vm_page_prot); if(result){ return -EAGAIN; } return 0; } struct file_operations mmapiomem_fops={ .owner=THIS_MODULE, .open=mmapiomem_open, .release=mmapiomem_release, .mmap=mmapiomem_mmap, }; struct cdev *mmap_cdev; struct class *mmap_class; int mmapiomem_init(void) { int result; int devno = MKDEV(MMAPIOMEM_DEV_MAJOR,0); mmap_buf_ptr = (char *)__get_free_pages(GFP_KERNEL,2);//alloc 4pages printk("%s,the mmap_buf_ptr is 0x%.8x\n",__func__,(unsigned int)mmap_buf_ptr); memset(mmap_buf_ptr,0,PAGE_SIZE *4); *((unsigned int *)(mmap_buf_ptr)) = 0x11111111; *((unsigned int *)(mmap_buf_ptr+PAGE_SIZE*1)) = 0x22222222; *((unsigned int *)(mmap_buf_ptr+PAGE_SIZE*2)) = 0x33333333; *((unsigned int *)(mmap_buf_ptr+PAGE_SIZE*3)) = 0x44444444; mmap_cdev = cdev_alloc(); result = register_chrdev_region(devno,1,"mmap_char_mem"); cdev_init(mmap_cdev,&mmapiomem_fops); mmap_cdev->owner = THIS_MODULE; result = cdev_add(mmap_cdev, devno,1); mmap_class = class_create(THIS_MODULE,"mmap_char_class"); if (IS_ERR(mmap_class)) { result= PTR_ERR(mmap_class); return -1; } device_create(mmap_class, NULL, devno, NULL, MMAPIOMEM_DEV_NAME); return 0; } void mmapiomem_exit(void) { if (mmap_cdev != NULL) cdev_del(mmap_cdev); device_destroy(mmap_class,MKDEV(MMAPIOMEM_DEV_MAJOR,0)); class_destroy(mmap_class); unregister_chrdev_region(MKDEV(MMAPIOMEM_DEV_MAJOR,0),1); } module_init(mmapiomem_init); module_exit(mmapiomem_exit); MODULE_LICENSE("Dual BSD/GPL");
应用部分:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <linux/vt.h> #define DEVICE_FILENAME "/dev/mmapiomem" #define MMAP_SIZE 0x8000 int main() { int ttydev; int dev; int loop,loop2; char *ptrdata; dev=open(DEVICE_FILENAME,O_RDWR|O_NDELAY); if(dev>=0){ printf("2)open the dev success\n"); ptrdata=(char*)mmap(0, MMAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0); for(loop = 0;loop < 64 * 5; loop ++) { for(loop2 = 0;loop2 < 16; loop2 ++) { printf("%.8x,",*((unsigned int *)(ptrdata + 4*(loop2 + 16 * loop)))); } printf("\n"); } if(ptrdata!=NULL){ printf("the value of ptrdata is 0x%.8x\n",*((unsigned int *)ptrdata)); } munmap(ptrdata,MMAP_SIZE); } close(dev); printf("6)here close the dev\n"); return 0; }
通过打印信息,可以看到已经获得了连续的物理内存(由内核分配,应用可以使用)。
相关文章推荐
- mmap将物理地址映射到用户空间
- Linux下将物理地址映射到用户空间
- Unix v6中对虚拟地址映射到物理地址以及在内核态如何访问用户空间的u值
- 设备地址映射到用户空间(mmap)
- PBR案例:电信用户通过网通服务器映射外网地址访问该服务器,无法访问?
- CMA连续物理内存用户空间映射---(一)
- 树莓派:mmap 点亮 led 灯 example,pi2 model B 直接物理地址映射
- 用户空间的虚拟地址如何转换得到实际的物理地址
- 虚拟字符驱动,申请n页内存,使用mmap映射到应用程序空间,用户就可以直接访问不需要任何同步机制
- mmap映射物理内存到用户空间的方法
- 【C语言】【unix c】使用mmap将物理地址映射到进程的虚拟地址空间
- mmap方法实现物理内存到用户虚拟地址的映射
- 函数 ioremap 物理地址到内核映射空间的映射函数
- 函数 ioremap 物理地址到内核映射空间的映射函数
- 【C语言】【unix c】使用mmap将文件映射到进程的虚拟地址空间,然后对内存的操作直接反应到文件中
- linux 内存映射 remap_pfn_range操作(内核地址映射到用户空间)
- CMA连续物理内存用户空间映射---(一)
- 用户内存空间映射mmap函数
- Linux内核---62.用户空间获得变量的物理地址
- [arm驱动]linux设备地址映射到用户空间 推荐