Linux内存映射(mmap)系列(1)
看到同事的代码中出现了mmap.所以自己私下学习学习,研究研究.....
http://www.cnblogs.com/lknlfy/archive/2012/04/27/2473804.html
(一).概述
内存映射,简而言之就是将用户空间的一段内存区域映射到内核空间,映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,相反,内核空间对这段区域的修改也直接反映用户空间。那么对于内核空间<---->用户空间两者之间需要大量数据传输等操作的话效率是非常高的。
首先,驱动程序先分配好一段内存,接着用户进程通过库函数mmap()来告诉内核要将多大的内存映射到内核空间(参考linux分类下面的<linux用户空间和内核空间>一文),内核经过一系列函数调用后调用对应的驱动程序的file_operation中的mmap函数,在该函数中调用remap_pfn_range()来建立映射关系。直白一点就是:驱动程序在mmap()中利用remap_pfn_range()函数将内核空间的一段内存与用户空间的一段内存建立映射关系。
用户空间mmap()函数:
void *mmap(void *start, size_t length, int prot, int flags,int fd, off_t offset)
start:用户进程中要映射的某段内存区域的起始地址,通常为NULL(由内核来指定)
length:要映射的内存区域的大小
prot:期望的内存保护标志
flags:指定映射对象的类型
fd:文件描述符(由open函数返回)
offset:要映射的用户空间的内存区域在内核空间中已经分配好的的内存区域中的偏移。大小为PAGE_SIZE的整数倍
二. 实现
首先在驱动程序分配一页大小的内存,然后用户进程通过mmap()将用户空间中大小也为一页的内存映射到内核空间这页内存上。映射完成后,驱动程序往这段内存写10个字节数据,用户进程将这些数据显示出来。
驱动程序:
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/gpio.h> #define DEVICE_NAME "mymap" static unsigned char array[]={,,,,,,,,,};
static unsigned char *buffer; static int my_open(struct inode *inode, struct file *file)
{
return ;
} static int my_map(struct file *filp, struct vm_area_struct *vma)
{
unsigned long page;
unsigned char i;
unsigned long start = (unsigned long)vma->vm_start;
//unsigned long end = (unsigned long)vma->vm_end;
unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start); //得到物理地址
page = virt_to_phys(buffer);
//将用户空间的一个vma虚拟内存区映射到以page开始的一段连续物理页面上
if(remap_pfn_range(vma,start,page>>PAGE_SHIFT,size,PAGE_SHARED))//第三个参数是页帧号,由物理地址右移PAGE_SHIFT得到
return -; //往该内存写10字节数据
for(i=;i<;i++)
buffer[i] = array[i]; return ;
} static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = my_open,
.mmap = my_map,
}; static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
}; static int __init dev_init(void)
{
int ret; //注册混杂设备
ret = misc_register(&misc);
//内存分配
buffer = (unsigned char *)kmalloc(PAGE_SIZE,GFP_KERNEL);
//将该段内存设置为保留
SetPageReserved(virt_to_page(buffer)); return ret;
} static void __exit dev_exit(void)
{
//注销设备
misc_deregister(&misc);
//清除保留
ClearPageReserved(virt_to_page(buffer));
//释放内存
kfree(buffer);
} module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LKN@SCUT");
用户程序:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h> #define PAGE_SIZE 4096 //一页大小2K int main(int argc , char *argv[])
{
int fd;
int i;
unsigned char *p_map; //打开设备
fd = open("/dev/mymap",O_RDWR);
if(fd < )
{
printf("open fail\n");
exit();
} //内存映射
//start:用户进程中要映射的某段内存区域的起始地址,通常为NULL(由内核来指定);length:要映射的内存区域的大小;prot:期望的内存保护标志;flags:指定映射对象的类型;fd:文件描述符(由open函数返回);offset:要映射的用户空间的内存区域在内核空间中已经分配好的的内存区域中的偏移。大小为PAGE_SIZE的整数倍
p_map = (unsigned char *)mmap(, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, );
if(p_map == MAP_FAILED)
{
printf("mmap fail\n");
goto here;
} //打印映射后的内存中的前10个字节内容
for(i=;i<;i++)
printf("%d\n",p_map[i]); here:
munmap(p_map, PAGE_SIZE);//解开关联
return ;
}
先加载驱动后执行应用程序,用户空间打印如下:
好吧,上面的东东很高大上,同事的意思呢,是可以把一个文件直接映射到内存中.然后可以就可以直接读文件了,见下图
输出结果:
可以看到,读到了原始文件的
1234444444444
abbbbbbbb
然后现在的文件内容改为
aaaaaaaaaaaaa
bbbbbbb
Linux内存映射(mmap)系列(1)的更多相关文章
- [转载]linux内存映射mmap原理分析【转】
转自:http://www.cnblogs.com/wanpengcoder/articles/5306688.html 转自:http://blog.csdn.net/yusiguyuan/arti ...
- Linux内存映射--mmap函数
Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明: 头文件: < ...
- 深入理解内存映射mmap
内存映射mmap是Linux内核的一个重要机制,它和虚拟内存管理以及文件IO都有直接的关系,这篇细说一下mmap的一些要点. 修改(2015-11-12):Linux的虚拟内存管理是基于mmap来实现 ...
- 计算机底层知识拾遗(九)深入理解内存映射mmap
内存映射mmap是Linux内核的一个重要机制,它和虚拟内存管理以及文件IO都有直接的关系,这篇细说一下mmap的一些要点. 修改(2015-11-12):Linux的虚拟内存管理是基于mmap来实现 ...
- 内存映射mmap的几个api及其使用
内存映射 mmap 内存映射mmap函数的作用是建立一段可以被两个或者多个程度读写的内存段,一个程序对他进行任何修改,对其它程序可见.同样,这个功能可以用在对文件的处理上,mmap函数创建一个指向一个 ...
- linux 内存映射-ioremap和mmap函数
最近开始学习Linux驱动程序,将内存映射和ioremap,mmap函数相关资料进行了整理 一,内存映射 对于提供了MMU(存储管理器,辅助操作系统进行内存管理,提供虚实地址转换等硬件支持)的处理器 ...
- 内存映射MMAP和DMA【转】
转自:http://blog.csdn.net/zhoudengqing/article/details/41654293 版权声明:本文为博主原创文章,未经博主允许不得转载. 这一章介绍Linux内 ...
- Linux 内存映射函数 mmap()函数详解
mmap将一个文件或者其它对象映射进内存.文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零.mmap在用户空间映射调用系统中作用很大.头文件 <sys/ ...
- 内存映射mmap
Table of Contents 1. 什么是mmap 2. 使用方法 2.1. mmap构造器的格式 2.2. 例子1 2.3. 例子2 3. 其它 4. 参考资料 什么是mmap 通常在Unix ...
随机推荐
- CSharp - Comparison between IComparer and IComparable
/* Author: Jiangong SUN */ I've already written an article introducing the usage of comparer here. I ...
- 关于Opengl中将24位BMP图片加入�一个alpha通道并实现透明的问题
#include <windows.h>#include <GL/glut.h>#include <GL/glaux.h>#include <stdio.h& ...
- Linux 精准获取进程pid--转
如果想在脚本里只获取PID,那么可以用如下脚本.目前收集两种方法: 方法一 $ps x|grep xxx |awk '{print $1}' e.g. ps x|grep java |awk '{p ...
- 随便说说removeFromSuperview方法
之前写过一篇关于removeFromSuperview方法处理的文章,写完后一直就没怎么更新这篇文章.这两天回过头来看看,感觉这篇文章有些地方写的不够严谨,而且还有一些自己理解错的地方,所以打算重写这 ...
- vi 使用笔记
基本A 当前行追加J 去除本行和下一行之间的换行符(写CSS利器)~ 光标所在处的字符进行大小写互换* 向前搜索目前光标所在的单词# 向后搜索目前光标所在的单词% 查找与光标所在处相匹配的反括号, 包 ...
- CentOS7安装Puppet+GitLab+Bind
添加Puppet官方源 rpm -Uvh https://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm 安装Puppet yum -y i ...
- CentOS7安装vim7.4
卸载自带vim yum remove vim-enhanced vim-common 下载vim包 wget ftp://ftp.vim.org/pub/vim/unix/vim-7.4.tar.bz ...
- android应用一(调用WebServices)
搞了一个月的android,现学现卖,终于还是搞完了,停下来,整理思路,写写记录吧. 我们知道android访问远程数据库主要有两种协议,一种是SOAP,另外一种就是HTTP.而我们再看看WebSer ...
- 解决Flash挡住层用z-index无效的问题
有时我们要用flash做透明背景结果发现加好之后下面的文字连接点击不了了,div下拉也给flash档住了,后来百度发现我们只要设置wmode参数就可解决了. 在HTML中,如果嵌入Flash,默认 ...
- Liferay环境搭建实录
1. 安装Liferay IDE:打开Eclipse的Help-->Eclipse Marketplace,在下图所示搜索框中输入liferay,回车搜索: 搜索结果如下图所示: 点击insta ...