Linux -----mmap进行内存映射的原理(未完成)

原创 2016年08月29日 00:22:07

     mmap系统调用的最终目的是将,设备或文件映射到用户进程的虚拟地址空间,实现用户进程对文件的直接读写,这个任务可以分为以下三步:

1.在用户虚拟地址空间中寻找空闲的满足要求的一段连续的虚拟地址空间,为映射做准备(由内核mmap系统调用完成)

       每个进程拥有3G字节的用户虚存空间。但是,这并不意味着用户进程在这3G的范围内可以任意使用,因为虚存空间最终得映射到某个物理存储空间(内存或磁盘空间),才真正可以使用。

       那么,内核怎样管理每个进程3G的虚存空间呢?概括地说,用户进程经过编译、链接后形成的映象文件有一个代码段和数据段(包括data段和bss段),其中代码段在下,数据段在上。数据段中包括了所有静态分配的数据空间,即全局变量和所有申明为static的局部变量,这些空间是进程所必需的基本要求,这些空间是在建立一个进程的运行映像时就分配好的。除此之外,堆栈使用的空间也属于基本要求,所以也是在建立进程时就分配好的,如图3.1所示:

 

 

 图3.1  进程虚拟空间的划分

      在内核中,这样每个区域用一个结构struct vm_area_struct 来表示.它描述的是一段连续的、具有相同访问属性的虚存空间,该虚存空间的大小为物理内存页面的整数倍。可以使用 cat /proc//maps来查看一个进程的内存使用情况,pid是进程号.其中显示的每一行对应进程的一个vm_area_struct结构.

下面是struct vm_area_struct结构体的定义:

  1. #include <linux/mm_types.h>

  2. /* This struct defines a memory VMM memory area. */

  3. struct vm_area_struct {
  4. struct mm_struct * vm_mm; /* VM area parameters */
  5. unsigned long vm_start;
  6. unsigned long vm_end;

  7. /* linked list of VM areas per task, sorted by address */
  8. struct vm_area_struct *vm_next;
  9. pgprot_t vm_page_prot;
  10. unsigned long vm_flags;

  11. /* AVL tree of VM areas per task, sorted by address */
  12. short vm_avl_height;
  13. struct vm_area_struct * vm_avl_left;
  14. struct vm_area_struct * vm_avl_right;

  15. /* For areas with an address space and backing store,
  16. vm_area_struct *vm_next_share;
  17. struct vm_area_struct **vm_pprev_share;
  18. struct vm_operations_struct * vm_ops;
  19. unsigned long vm_pgoff; /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */
  20. struct file * vm_file;
  21. unsigned long vm_raend;
  22. void * vm_private_data; /* was vm_pte (shared mem) */
  23. };

      通常,进程所使用到的虚存空间不连续,且各部分虚存空间的访问属性也可能不同。所以一个进程的虚存空间需要多个vm_area_struct结构来描述。在vm_area_struct结构的数目较少的时候,各个vm_area_struct按照升序排序,以单链表的形式组织数据(通过vm_next指针指向下一个vm_area_struct结构)。但是当vm_area_struct结构的数据较多的时候,仍然采用链表组织的化,势必会影响到它的搜索速度。针对这个问题,vm_area_struct还添加了vm_avl_hight(树高)、vm_avl_left(左子节点)、vm_avl_right(右子节点)三个成员来实现AVL树,以提高vm_area_struct的搜索速度。

  假如该vm_area_struct描述的是一个文件映射的虚存空间,成员vm_file便指向被映射的文件的file结构,vm_pgoff是该虚存空间起始地址在vm_file文件里面的文件偏移,单位为物理页面。

图3.2  进程虚拟地址示意图 

因此,mmap系统调用所完成的工作就是准备这样一段虚存空间,并建立vm_area_struct结构体,将其传给具体的设备驱动程序.

2. 建立虚拟地址空间和文件或设备的物理地址之间的映射(设备驱动完成)

  建立文件映射的第二步就是建立虚拟地址和具体的物理地址之间的映射,这是通过修改进程页表来实现的.mmap方法是file_opeartions结构的成员:

  int (*mmap)(struct file *,struct vm_area_struct *);


linux有2个方法建立页表:

(1) 使用remap_pfn_range一次建立所有页表.

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

返回值:

成功返回 0, 失败返回一个负的错误值
参数说明:

vma 用户进程创建一个vma区域


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


pfn 页帧号, 对应虚拟地址应当被映射的物理地址. 这个页帧号简单地是物理地址右移 PAGE_SHIFT 位. 对大部分使用, VMA 结构的 vm_paoff 成员正好包含你需要的值. 这个函数影响物理地址从 (pfn<<page_shift) 到 (pfn<<page_shift)+size.< span="" style="word-wrap: break-word;">


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


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

(2) 使用nopage VMA方法每次建立一个页表项.

   struct page *(*nopage)(struct vm_area_struct *vma, unsigned long address, int *type);

返回值:

成功则返回一个有效映射页,失败返回NULL.

参数说明:

address 代表从用户空间传过来的用户空间虚拟地址.

返回一个有效映射页.


(3) 使用方面的限制:

remap_pfn_range不能映射常规内存,只存取保留页和在物理内存顶之上的物理地址。因为保留页和在物理内存顶之上的物理地址内存管理系统的各个子模块管理不到。640 KB 和 1MB 是保留页可能映射,设备I/O内存也可以映射。如果想把kmalloc()申请的内存映射到用户空间,则可以通过mem_map_reserve()把相应的内存设置为保留后就可以。

linux内存映射mmap原理分析

一直都对内存映射文件这个概念很模糊,不知道它和虚拟内存有什么区别,而且映射这个词也很让人迷茫,今天终于搞清楚了。。。下面,我先解释一下我对映射这个词的理解,再区分一下几个容易混淆的概念,之后,什么是内...

linux内存映射mmap原理分析

一直都对内存映射文件这个概念很模糊,不知道它和虚拟内存有什么区别,而且映射这个词也很让人迷茫,今天终于搞清楚了。。。下面,我先解释一下我对映射这个词的理解,再区分一下几个容易混淆的概念,之后,什么是内...

linux内存映射mmap原理分析

linux内存映射mmap原理分析 内存映射,简而言之就是将用户空间的一段内存区域映射到内核空间,映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,同样,内核空间对这段区域...

linux mmap文件内存映射机制

  • 2011年10月16日 16:30
  • 71KB
  • 下载

linux内存映射mmap原理分析

一直都对内存映射文件这个概念很模糊,不知道它和虚拟内存有什么区别,而且映射这个词也很让人迷茫,今天终于搞清楚了。。。下面,我先解释一下我对映射这个词的理解,再区分一下几个容易混淆的概念,之后,什么是内...

linux内存映射mmap原理分析

一直都对内存映射文件这个概念很模糊,不知道它和虚拟内存有什么区别,而且映射这个词也很让人迷茫,今天终于搞清楚了。。。下面,我先解释一下我对映射这个词的理解,再区分一下几个容易混淆的概念,之后,什么是内...

Linux 内存映射函数 mmap()函数详解

原文地址:http://blog.csdn.net/dlutbrucezhang/article/details/9080173 一、概述           内存映射,简而言之就是将用户空间的一...

linux内存映射函数 mmap

Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明: 一、头文件:...

Unix/Linux的 mmap()内存映射

mmap() UNIX网络编程第二卷进程间通信对mmap函数进行了说明。该函数主要用途有三个: 1、将一个普通文件映射到内存中,通常在需要对文件进行频繁读写时使用,这样用内存读写取代I/O读写...
  • sunny04
  • sunny04
  • 2015年06月09日 15:07
  • 717
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux -----mmap进行内存映射的原理(未完成)
举报原因:
原因补充:

(最多只允许输入30个字)