Chinaunix首页 | 论坛 | 博客
  • 博客访问: 30766
  • 博文数量: 7
  • 博客积分: 67
  • 博客等级: 民兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-22 14:53
文章分类
文章存档

2012年(7)

分类:

2012-01-06 17:22:45

原文地址:mmap设备操作 作者:luozhiyong131

mmap系统调用

void* mmap ( void * addr , size_t len , int prot , int flags , int fd , off_t offset )内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要再调用readwrite等操作。

Addr    指定映射的起始地址, 通常设为NULL, 由系统指定。

Length:    映射到内存的文件长度。

Prot     映射区的保护方式, 可以是:

PROT_EXEC: 映射区可被执行

PROT_READ: 映射区可被读取

PROT_WRITE: 映射区可被写入

PROT_NONE: 映射区不能存取

Flags: 映射区的特性, 可以是:

MAP_SHARED:     写入映射区的数据会复制回文件, 且允许其他映射该文件的进程共享。

MAP_PRIVATE:     对映射区的写入操作会产生一个映射区的复制(copy-on-write), 对此区域所做的修改不会写回原文件。

Fd:   open返回的文件描述符, 代表要映射的文件。

Offset:    以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射。

 

解除映射

int munmap(void *start,size_t length)

功能:取消参数start所指向的映射内存,参数length表示欲取消的内存大小。

返回值:解除成功返回0,否则返回-1,错误原因存于errno中。

 

虚拟内存区域

虚拟内存区域是进程的虚拟地址空间中的一个同质区间,即具有同样特性的连续地址范围。一个进程的内存映象由下面几部分组成:程序代码、数据、BSS和栈区域,以及内存映射的区域。一个进程的内存区域可以通过查看/proc/pid/maps

每一行的域为:

start_end perm offset major:minor inode

 Start: 该区域起始虚拟地址

 End: 该区域结束虚拟地址

 Perm: 读、写和执行权限;表示对这个区域,允许进程做什么。这个域的最后一个字符要么是p表示私有的,要么是s表示共享的。

 Offset: 被映射部分在文件中的起始地址

 Majorminor:主次设备号

 Inode:索引结点

 

Linux内核使用结构vm_area_struct)来描述虚拟内存区域,其中几个主要成员如下:

unsigned long vm_start     虚拟内存区域起始地址

unsigned long vm_end        虚拟内存区域结束地址

unsigned long vm_flags      该区域的标记。如:VM_IOVM_RESERVED

VM_IO将该VMA标记为内存映射的IO区域,VM_IO会阻止系统将该区域包含在进程的存放转存(core dump )中,VM_RESERVED标志内存区域不能被换出。

 

映射一个设备是指把用户空间的一段地址关联到设备内存上。当程序读写这段用户空间的地址时,它实际上是在访问设备。

mmap方法是file_oprations结构的成员,在mmap系统调用发出时被调用。在此之前,内核已经完成了很多工作。mmap设备方法所需要做的就是建立虚拟地址到物理地址的页表int (*mmap) (struct file *, struct vm_area_struct *)

 

mmap完成页表的建立方法:

1、使用remap_pfn_range一次建立所有页表;

2、使用nopage VMA方法每次建立一个页表。

构造页表的工作remap_pgn_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得到。

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_pgn_range(vma, vma->vm_start, virt_to_phys(dev- >data)>> PAGE_SHIFT, size, vma->vm_page_prot))

return -EAGAIN;

return 0;

}

 

国嵌课件:  设备驱动-3.pdf   

实例代码: 字符驱动程序的mmap设备方法.rar  

阅读(937) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~