Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1271368
  • 博文数量: 482
  • 博客积分: 13297
  • 博客等级: 上将
  • 技术积分: 2890
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-12 16:25
文章分类

全部博文(482)

文章存档

2012年(9)

2011年(407)

2010年(66)

分类: LINUX

2011-04-23 15:54:15

结构体struct vm_area_struct 

当用户空间进程调用mmap,将设备内存映射到它的地址空间时,系统通过创建一个表示该映射的VMA(虚拟内存区)作为响应。支持mmap的驱动程序需要帮助进程完成VMA的初始化。

该结构中的重要成员:

    unsigned long vm_start;

   unsigned long vm_end; 

VMA所覆盖的虚拟地址范围。

struct file * vm_file;

指向与该区域相关联的file结构体指针。

unsigned long vm_pgoff;

以页为单位,文件中该区域的偏移量。当映射一个文件或设备时,它是该区域中被映射的第一页在文件中的位置。

unsigned long vm_flags;

 描述该区域的一套标志。驱动程序最感兴趣的标志是VM_IOVM_RESERVED

VM_IOVMA设置成一个内存映射IO区域。VM_IO会阻止系统将该区域包含在进程的核心转存中。VM_RESERVED告诉内存管理系统不要将该VMA交换出去;大多数设备映射中都设置该标志。

struct vm_operations_struct * vm_ops;

内核能调用的一套函数,用来对该内存区进行操作。它的存在表示内存区域是一个内核“对象”。

一个驱动程序只映射与其外围设备相关的一小段地址,而不是映射全部地址的例子。为了向用户空间只映射部分内存的需要,驱动程序只需要使用偏移量即可。下面的代码揭示了驱动程序如何对起始于物理地址simple_region_start(页对齐),大小为simple_region_size字节的区域进行映射的工作过程:

(注:“外围设备” 即是设备文件。 vm_pgoff; 为要映射区域在“外围设备”文件中的偏移量(以页为单位),“外围设备”文件即是指外围设备的一段内存。这个偏移量即使相对于这段内存开始的偏移量)

unsigned long off = vma->vm_pgoff << PAGE_SHIFT; //以页为单位转为以字节为单位

unsigned long physical = simple_region_start + off; //计算相对于文件开始的偏移

unsigned long vsize = vma->vm_end - vma->vm_start; //要映射的区域大小

unsigned long psize = simple_region_size - off; //偏移之后文件的剩余空间

if (vsize > psize) //是否偏移之后文件的剩余空间不足以满足要映射的空间大小

     return -EINVAL; /* 跨度过大*/

remap_pfn_range(vmavma_>vm_start, physical, vsize, vma->vm_page_prot);

(注:我认为physical应向右移PAGE_SHIFT,因为函数此处为页帧号

                          

关于函数 remap_pfn_range 和 io_remap_page_range

建立新页来映射物理地址的工作由 remap_pfn_range 和 io_remap_page_range 来处理它们有下面的原型:

int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long pfn, unsigned long size, pgprot_t prot); 

int io_remap_page_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long phys_addr, unsigned long size, pgprot_t prot); 

由这个函数返回的值常常是 或者一个负的错误值让我们看看这些函数参数的确切含义:

vma

页范围被映射到的虚拟内存区

virt_addr

重新映射应当开始的用户虚拟地址这个函数建立页表为这个虚拟地址范围从 virt_addr 到 virt_addr_size.

pfn

页帧号对应虚拟地址应当被映射的物理地址这个页帧号简单地是物理地址右移 PAGE_SHIFT 对大部分使用VMA 结构的 vm_paoff 成员正好包含你需要的值这个函数影响物理地址从 (pfn<到 (pfn<

size

正在被重新映射的区的大小以字节.

prot

给新 VMA 要求的"protection". 驱动可(并且应当)使用在 vma->vm_page_prot 中找到的值.

====

http://chxxxyg.blog.163.com/blog/static/15028119320103982342980/

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