博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux-mmap映射物理内存到用户空间
阅读量:4165 次
发布时间:2019-05-26

本文共 3871 字,大约阅读时间需要 12 分钟。

转自:

在内核申请一片物理内存,映射到用户空间使用的方法。环境:Linux ubuntu 4.10.0-42-generic。

方法经博主测试,测试环境:ubuntu 16.04,内核版本:linux-4.15

一、内核驱动模块

map.c:

#include 
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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; unsigned long page; vma->vm_flags |= (VM_IO | VM_LOCKED | (VM_DONTEXPAND | VM_DONTDUMP)); vma->vm_flags|=VM_IO; page = virt_to_phys(mmap_buf_ptr); result = remap_pfn_range(vma, vma->vm_start, ((unsigned int)page)>>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); printk("%s,the mmap_buf_ptr is 0x%p\n",__func__,mmap_buf_ptr); memset(mmap_buf_ptr,0,PAGE_SIZE*4); *((unsigned int *)(mmap_buf_ptr)) = 0xc3a21b44; *((unsigned int *)(mmap_buf_ptr+0x4)) = 0xab8812df; 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");

Makefile:

obj-m := map.oall:	$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:	$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

以上是内核部分,主要是创建一个字符设备,配置其mmap函数,分配连续内存。分配了4pages,并将首地址开始初始化了8bytes。

具体使用方法是:make    insmod map.ko    dmesg-c

最后打印出:

mmapiomem_init,the mmap_buf_ptr is 0xffff880129880000

二、用户态测试

user_test.c:

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_FILENAME "/dev/mmapiomem" #define MMAP_SIZE 0x8000 int main() { int ttydev; int dev,i; uint8_t *ptrdata; dev=open(DEVICE_FILENAME,O_RDWR|O_NDELAY); if(dev>=0) { printf("2)open the dev success\n"); ptrdata=(uint8_t*)mmap((void*)0x000000000f000000, MMAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0); if(ptrdata!=NULL) { printf("the value of ptrdata0 is 0x%02x\n",*ptrdata); printf("the value of ptrdata1 is 0x%02x\n",*(ptrdata+0x1)); printf("the value of ptrdata2 is 0x%02x\n",*(ptrdata+0x2)); printf("the value of ptrdata3 is 0x%02x\n",*(ptrdata+0x3)); printf("the value of ptrdata4 is 0x%02x\n",*(ptrdata+0x4)); printf("the value of ptrdata5 is 0x%02x\n",*(ptrdata+0x5)); printf("the value of ptrdata6 is 0x%02x\n",*(ptrdata+0x6)); printf("the value of ptrdata7 is 0x%02x\n",*(ptrdata+0x7)); printf("the addr_map is: %p\n",ptrdata); } } close(dev); printf("6)here close the dev\n"); return 0; }

在虚拟机上测试结果如下:

可以看到在虚拟机下测试不成功,移步真机得到如下测试结果:

真机测试成功,可以看到,已经映射成功并且读取了我们之前初始化的值,返回了一个用户空间内存地址。因为程序结束后映射会取消掉,所以如果需要使用该地址的话,直接把这个addr_map传给自己的其他接口函数就行。

 

转载地址:http://othxi.baihongyu.com/

你可能感兴趣的文章
数据库与模式的区别
查看>>
数字签名的原理
查看>>
showDialog
查看>>
Flex 拖拽范例
查看>>
flash builder 4 编译器参数
查看>>
flex常用网站
查看>>
flex 页面跳转
查看>>
cat | wc -l 少一行的问题
查看>>
socket 科普文章
查看>>
Mutex, semaphore, spinlock的深度解析
查看>>
pthread线程使用小结
查看>>
A Game of Thrones(59)
查看>>
2018.3.19
查看>>
A Game of Thrones(97)
查看>>
A Game of Thrones(98)
查看>>
2018.3.20
查看>>
2018.3.21
查看>>
2018.3.22
查看>>
2018.3.23
查看>>
A Game of Thrones(102)
查看>>