Linux内核驱动--mmap设备方法【原创】
mmap系统调用(功能)
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
内存映射函数mmap , 负责把文件内容映射到进程的虚拟内存空间,通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要再调用read, write等操作。
addr: 指定映射的起始地址,通常设为NULL, 由系统指定。
len: 映射到内存的文件长度
prot: 映射区的保护方式, 可以是:
PROT_EXEC: 映射区可被执行
PROT_READ: 映射区可被读取
PROT_WRITE: 映射区可被写入
flags: 映射区的特性,可以是:
MAP_SHARED:
写入映射区的数据会复制回文件,且允许其他映射该文件的进程共享
MAP_PRIVATE:
对映射区的写入操作会产生一个映射区的复制(copy-on-write), 对此区域所做的修改不会写回原文件。
fd: 由open返回的文件描述符,代表要映射的文件
offset: 以文件开始处的偏移量,必须是分页大小的整数倍,通常为0,表示从文件开头映射
解除映射
int munmap(void *start, size_t length)
功能:
取消参数start所指向的映射内存,参数length表示欲取消的内存大小
返回值:
解除成功返回0,否则返回-1,错误原因存于errno中。
注意:
mmap 不影响原文件的长度,如果写入的长度超出了原文件的长度,那么就只能写入原文件的长度大小的数据内容
代码:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main(void)
-{
| int fd;
| char *start=NULL;
| char buf[100];
|
| fd = open("t.txt", O_RDWR | O_CREAT);
| start = mmap(NULL, 100, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
| strcpy(buf, start);
| printf("buf is %s\r\n", buf);
|
| strcpy(start, "sky is hello");
| munmap(start, 100);
| close(fd);
|
| return 0;
|}
虚拟内存区域
虚拟内存区域是进程的虚拟地址空间中的一个同质区间,即具有同样特性的连续地址
范围。一个进程的内存映像由下面几部分组成:程序代码、数据、BSS和栈区域,以及内存
映射的区域。
一个进程的内存区域可以通过 /proc/pid/maps来查看
例如:cat /proc/6/maps
每一行的域为:
Start_end perm offset major:minor inode
Start: 该区域起始虚拟地址
End:该区域结束虚拟地址
Perm:读、写和执行权限;表示对这个区域,允许进程做什么。这个域的最后一个字符要么是p表示私有的,要么是s表示共享的
Offset: 被映射部分在文件中的起始地址
Major、minor: 主次设备号
Inode: 索引结点
Linux内核使用结构vm_area_struct
(<linux/mm_types.h>)来描述虚拟内存区域,其中几个主要成员如下:
unsigned long vm_start 虚拟内存区域起始地址
unsigned long vm_end 虚拟内存区域结束地址
unsigned long vm_flags 该区域的标记。如:VM_IO和VM_RESERVED。
VM_IO将该VMA标记为内存映射的IO区域,VM_IO会阻止系统将该区域包含在进程的存放转存(core dump)中, VM_RESERVED 标志内存区域不能被换出。
mmap设备操作
映射一个设备是指把用户空间的一段地址关联到设备内存上。当程序读写这段用户空间的地址时,它实际上是在访问设备。
内存管理单元去关联的,通过页式管理关联的,具体如何关联的去了解linux内存管理吧。
mmap设备方法需要完成什么功能?
Mmap方法是file_oprations结构的成员,在mmap系统调用发出时被调用。在此之前,内核已经完成了很多工作。Mmap设备方法所需要做的就是建立虚拟地址到物理地址的页表。
int (*mmap) (struct file*, struct vm_area_struct *)
mmap如何完成页表的建立?
方法有二:
1、 使用remap_pfn_range一次建立所有页表;
2、 使用nopage VMA方法每次建立一个页表
构造页表的工作可由remap_pfn_range函数完成,原型如下:
int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot)
vma: 虚拟内存区域指针
virt_addr: 虚拟地址的起始值
pfn: 要映射的物理地址所在的物理页帧号,可将物理地址>>PAGE_SHIFT得到,这个宏定义是12,就是除以4KB
size: 要映射的区域的大小
prot: VMA的保护属性
例子:
int memdev_mmap(struct file *filp, struct vm_area_struct *vma)
{
//设置保护属性
vma->vm_flags |= VM_IO;
vma->vm_flags |= VM_RESERVED;
if (remap_pfm_range(vma, vma->vma-start, virt_to_phys(dev->data)>>PAGE_SHIFT,
size, vma->vm_page_prot))
return –EAGAIN;
return 0;
}
Dev-data是虚拟地址,就要用virt_to_phys转换为物理地址,如果是物理地址,那就不用转化了。
这样就实现了mmap的设备操作
新浪博客:http://blog.sina.com.cn/u/2049150530
博客园:http://www.cnblogs.com/sky-heaven/
知乎:http://www.zhihu.com/people/zhang-bing-hua
Linux内核驱动--mmap设备方法【原创】的更多相关文章
- linux内核驱动模型
linux内核驱动模型,以2.6.32内核为例.(一边写一边看的,有点乱.) 1.以内核对象为基础.用kobject表示,相当于其它对象的基类,是构建linux驱动模型的关键.具有相同类型的内核对象构 ...
- linux 内核驱动--Platform Device和Platform_driver注册过程
linux 内核驱动--Platform Device和Platform_driver注册过程 从 Linux 2.6 起引入了一套新的驱动管理和注册机制 :Platform_device 和 Pla ...
- 【引用】Linux 内核驱动--多点触摸接口
本文转载自James<Linux 内核驱动--多点触摸接口> 译自:linux-2.6.31.14\Documentation\input\multi-touch-protocol.t ...
- Linux内核驱动开发之KGDB原理介绍及kgdboe方式配置
接博文<Linux内核驱动开发之KGDB单步调试内核(kgdboc方式)>.上篇博文中,仅简单介绍使用串口的Kgbd的流程(kgdboc方式),本文将重点介绍KGDB调试Linux内核的原 ...
- 嵌入式C语言自我修养 02:Linux 内核驱动中的指定初始化
2.1 什么是指定初始化 在标准 C 中,当我们定义并初始化一个数组时,常用方法如下: ] = {,,,,,,,,}; 按照这种固定的顺序,我们可以依次给 a[0] 和 a[8] 赋值.因为没有对 a ...
- Linux内核源码分析方法_转
Linux内核源码分析方法 转自:http://www.cnblogs.com/fanzhidongyzby/archive/2013/03/20/2970624.html 一.内核源码之我见 Lin ...
- Linux内核驱动学习(八)GPIO驱动模拟输出PWM
文章目录 前言 原理图 IO模拟输出PWM 设备树 驱动端 调试信息 实验结果 附录 前言 上一篇的学习中介绍了如何在用户空间直接操作GPIO,并写了一个脚本可以产生PWM.本篇的学习会将写一个驱动操 ...
- Linux内核驱动学习(六)GPIO之概览
文章目录 前言 功能 如何使用 设备树 API 总结 前言 GPIO(General Purpose Input/Output)通用输入/输出接口,是十分灵活软件可编程的接口,功能强大,十分常用,SO ...
- linux内核中创建线程方法
1.头文件 #include <linux/sched.h> //wake_up_process() #include <linux/kthread.h> //kthread_ ...
随机推荐
- 自学Aruba7.3-Aruba安全认证-802.1x认证(web页面配置)
点击返回:自学Aruba之路 自学Aruba7.3-Aruba安全认证-802.1x认证(web页面配置) 步骤1 建立AP Group,命名为test802-group 步骤2 将AP加入到AP ...
- 丢手帕问题 (约瑟夫问题)Java实现
问题: 丢手帕游戏是约瑟夫问题的一个变种,游戏很简单,N个小孩围成一个圈,标号为1到N,从编号为m的小孩开始报数,报到第L个小孩退出游戏,然后下一个小孩继续从1开始报数,数到第L个小孩退出游戏,如此循 ...
- oracle导出导入数据库
一.给空表分配空间: 这一步一定要做,否则空表不能导出. 首先连接你要导出的库,在该库上执行以下sql: select 'alter table '||table_name||' allocate e ...
- 【BZOJ1814】Ural 1519 Formula 1 (插头dp)
[BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...
- 完全卸载迈克菲Mcafee的工具
http://yunpan.cn/cZT4vGMMbGVns 访问密码 d257
- 基于SpringMVC的文件(增删改查)上传、下载、更新、删除
一.项目背景 摘要:最近一直在忙着项目的事,3个项目过去了,发现有一个共同的业务,那就是附件的处理,附件包括各种文档,当然还有图片等特殊文件,由于时间的关系,每次都是匆匆忙忙的搞定上线,称这项目的空档 ...
- 解决IIS8中 URLRewriter 不能使用的方法
1.把应用程序池改成集成 2.的web.config 加入代码 <system.webServer> <validation validateIntegratedModeConfig ...
- CodeForces892E 可撤销并查集/最小生成树
http://codeforces.com/problemset/problem/892/E 题意:给出一个 n 个点 m 条边的无向图,每条边有边权,共 Q 次询问,每次给出 ki 条边,问这些边 ...
- SSD详解
This results in a significant improvement in speed for high-accuracy detection(59 FPS with mAP 74.3% ...
- 高级Linux运维工程师必备技能(扫盲篇)
高级Linux运维工程师必备技能(扫盲篇) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在了解文件系统之前,我们要学习一下磁盘存储数据的方式,大家都知道文件从内存若要持久化存储的 ...