Mmap设备方法---那些年我们一起玩嵌入式驱动
2012-06-29 21:04
232 查看
mmap设备方法)
Mmap系统调用(功能)
Void* mmap(void * add, size_t len , int prot, int flags, int fd, off_t offset)
Mmap系统调用(参数)
*Addr
指定映射的起始地址,通常设为NULL,由系统指定。
*Length:
映射到内存的文件长度
*port:
映射区的保护方式,可以是:
PROT_EXEC:映射区可被执行;
PROT_READ:映射去可被读取;
PROT_WRITE:映射区可被写入;
PROT_NONE:映射区不能存取;
*flags:
映射区的特性,可以是:
# MAP_SHARED:
写入映射区的数据会复制回文件,且允许其他映射该文件的进程共享。
#MAP_PRIVATE:
对映射区的写入操作产生一个映射区的复制(copy-on-write),对此区域所做的修改不会协会原文件。
Fd:
由open返回的文件描述符,代表要映射的文件。
Offset:
以文件开始处偏移量,必须是分页大小的整数倍,通常为0,表示从文件头开始映射。
内存映射函数mmap,负责把文件内容映射到进程的虚拟空间,通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要在调用read,write等操作。
左边是进程的虚拟地址空间;右边是文件;
解除映射
Int munmap(void *start,size_t length)
功能:
取消参数start所指向的映射内存,参数length表示与取消的内存的大小。
(start所指向的映射内存,即mmap()的返回值)
返回值:
解除成功返回0,否则返回-1,错误原因存在errno中。
源程序:
示例:
#include<stdio.h>
#include<sys/types.h>
#include<sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mma.h>
Int main()
{
int fd;
char *start;
char buf[100];
/*打开文件*/
fd=open(“testfile”,O_RDWR);
start=mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); //把文件testfile进程映射到虚拟空间中去
//映射文件的地址直接通过start返回,以后操作文件就直接使用这个地址
/*读出数据*/
Strcpy(buf,start);/*把buf中的内容直接拷贝到start中去*/
printf(“buf=%s\n”,buf);
/*写入数据*/
Strcpy(start,”buf is not null!”);/*把字符串直接写到start中*/
Munmap(start,100);/*解除映射*/
close(fd); /*关闭文件*/
return 0;
}
源文件:
1. 通过mmap函数返回映射地址(初始位置)start;
2. 利用返回的start地址通过strcpy()写入、读出函数;
3. 读写完后,接触映射;
虚拟内存区域
虚拟内存区域是进程的虚拟地址空间中的一个同质区间,即具有同样特性的连续地址范围。一个进程的内存映像由下面几部分组成:程序代码、数据、BSS和栈区域,以及内存映射的区域。
虚拟内存区域:
每一行的域为:
Start _end perm offset major: minor inode
*start:该区域起始虚拟地址
*end:该区域结束虚拟地址
*perm :读、写和执行权限;表示对这个区域,允许进程做什么。这个区域的最后一个字符要么是P表示私有的,要么是s表示共享的。
*offset :被映射部分在文件中的起始地址
*major、minor:主设备号;
*inode :索引节点
Vm_area_struct
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设备操作
映射一个设备是指把用户空间的一段地址关联到设备内存上。当程序读写这段用户空间的地址时,它实际上是在访问设备。
Mmap设备操作
Mmap设备方法需要完成什么功能?
Mmap方法是file_oprations结构的成员,在mmap系统调用发出时被调用。在此之前,内核已经完成了很多工作。mmap设备方法所需要做的就是建立虚拟地址到物理地址的页表。
内核可以帮我找到一块可以用的虚拟地址,怎么告诉我?
就是通过struct vm_area_struct
参数告诉我的。
Mmap如何完成页表的建立?
方法有二:
1. 使用remap_pfn_range一次建立所有页表;
2. 使用nopage VMA方法每次建立一个页表。
我们使用的是第一种:remap_pfn_range一次建立所有页表;
Vma :(内核帮我们找到的虚拟内核区间)
虚拟内存区域指针
Virt_addr:(关联的虚拟地址)
虚拟地址的起始值;
Pfn:(关联的物理地址)
要映射的物理地址所在的物理页帧号,可将物理地址>>PAGE_SHIRT得到。
>>PAGE_SHIRT(PAGE_SHIRT是12,即右移12位,相当于除以4k)
Size:(关联的长度多大)
要映射的区域的大小
Prot:(关联的属性)
VMA的保护属性
分析思路顺序按照如下颜色;
思路一:在file_operations结构体中添加mmap函数;
思路二:实现mmap函数、如上;
驱动中的mmap函数:
1. 设置属性;
2. 建立虚拟地址到物理地址的页表;
Mmap系统调用(功能)
Void* mmap(void * add, size_t len , int prot, int flags, int fd, off_t offset)
Mmap系统调用(参数)
*Addr
指定映射的起始地址,通常设为NULL,由系统指定。
*Length:
映射到内存的文件长度
*port:
映射区的保护方式,可以是:
PROT_EXEC:映射区可被执行;
PROT_READ:映射去可被读取;
PROT_WRITE:映射区可被写入;
PROT_NONE:映射区不能存取;
*flags:
映射区的特性,可以是:
# MAP_SHARED:
写入映射区的数据会复制回文件,且允许其他映射该文件的进程共享。
#MAP_PRIVATE:
对映射区的写入操作产生一个映射区的复制(copy-on-write),对此区域所做的修改不会协会原文件。
Fd:
由open返回的文件描述符,代表要映射的文件。
Offset:
以文件开始处偏移量,必须是分页大小的整数倍,通常为0,表示从文件头开始映射。
内存映射函数mmap,负责把文件内容映射到进程的虚拟空间,通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要在调用read,write等操作。
左边是进程的虚拟地址空间;右边是文件;
解除映射
Int munmap(void *start,size_t length)
功能:
取消参数start所指向的映射内存,参数length表示与取消的内存的大小。
(start所指向的映射内存,即mmap()的返回值)
返回值:
解除成功返回0,否则返回-1,错误原因存在errno中。
源程序:
示例:
#include<stdio.h>
#include<sys/types.h>
#include<sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mma.h>
Int main()
{
int fd;
char *start;
char buf[100];
/*打开文件*/
fd=open(“testfile”,O_RDWR);
start=mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); //把文件testfile进程映射到虚拟空间中去
//映射文件的地址直接通过start返回,以后操作文件就直接使用这个地址
/*读出数据*/
Strcpy(buf,start);/*把buf中的内容直接拷贝到start中去*/
printf(“buf=%s\n”,buf);
/*写入数据*/
Strcpy(start,”buf is not null!”);/*把字符串直接写到start中*/
Munmap(start,100);/*解除映射*/
close(fd); /*关闭文件*/
return 0;
}
源文件:
1. 通过mmap函数返回映射地址(初始位置)start;
2. 利用返回的start地址通过strcpy()写入、读出函数;
3. 读写完后,接触映射;
虚拟内存区域
虚拟内存区域是进程的虚拟地址空间中的一个同质区间,即具有同样特性的连续地址范围。一个进程的内存映像由下面几部分组成:程序代码、数据、BSS和栈区域,以及内存映射的区域。
虚拟内存区域:
每一行的域为:
Start _end perm offset major: minor inode
*start:该区域起始虚拟地址
*end:该区域结束虚拟地址
*perm :读、写和执行权限;表示对这个区域,允许进程做什么。这个区域的最后一个字符要么是P表示私有的,要么是s表示共享的。
*offset :被映射部分在文件中的起始地址
*major、minor:主设备号;
*inode :索引节点
Vm_area_struct
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设备操作
映射一个设备是指把用户空间的一段地址关联到设备内存上。当程序读写这段用户空间的地址时,它实际上是在访问设备。
Mmap设备操作
Mmap设备方法需要完成什么功能?
Mmap方法是file_oprations结构的成员,在mmap系统调用发出时被调用。在此之前,内核已经完成了很多工作。mmap设备方法所需要做的就是建立虚拟地址到物理地址的页表。
内核可以帮我找到一块可以用的虚拟地址,怎么告诉我?
就是通过struct vm_area_struct
参数告诉我的。
Mmap如何完成页表的建立?
方法有二:
1. 使用remap_pfn_range一次建立所有页表;
2. 使用nopage VMA方法每次建立一个页表。
我们使用的是第一种:remap_pfn_range一次建立所有页表;
Vma :(内核帮我们找到的虚拟内核区间)
虚拟内存区域指针
Virt_addr:(关联的虚拟地址)
虚拟地址的起始值;
Pfn:(关联的物理地址)
要映射的物理地址所在的物理页帧号,可将物理地址>>PAGE_SHIRT得到。
>>PAGE_SHIRT(PAGE_SHIRT是12,即右移12位,相当于除以4k)
Size:(关联的长度多大)
要映射的区域的大小
Prot:(关联的属性)
VMA的保护属性
分析思路顺序按照如下颜色;
思路一:在file_operations结构体中添加mmap函数;
思路二:实现mmap函数、如上;
驱动中的mmap函数:
1. 设置属性;
2. 建立虚拟地址到物理地址的页表;
相关文章推荐
- 那些年,我们一起学的嵌入式
- Linux内核驱动--mmap设备方法【原创】
- Cstyle的嵌入式之:那些年我们一起写过的单片机程序,世上最简单的单片机程序
- 字符设备驱动另一种写法—mmap方法操作LED
- 那些年我们一起清除过的浮动
- S3C6410 按键驱动(五) --- 驱动源代码(我采用自动分配设备号的方法,注册设备)
- 嵌入式Linux系统中I2C总线设备的驱动设计
- 问题 A: 那些年我们一起考过的浙大
- 国嵌内核驱动进阶班-7-4(Poll设备方法)
- 那些年,我们曾一起追的高富帅科技产品
- 驱动中通过设备链接名取得磁盘符号的方法
- Android 设备 USB 通用调试驱动的安装方法
- Linux设备驱动之内存映射--mmap--转
- 那些年,我们应该读的书 《Effective_C#_中文版_改善C#程序的50种方法》第一章
- 11-S3C2440驱动学习(七)嵌入式linux-字符设备的另一种写法及RTC驱动程序分析和字符设备驱动框架总结
- 那些年我们一起清除过的浮动
- ok6410学习笔记(8.mmap地址映射之mmap驱动方法)
- 转: 嵌入式linux下usb驱动开发方法--看完少走弯路
- 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入
- Linux设备驱动之mmap设备操作