内存映射_内存映射文件 - CSDN
精华内容
参与话题
  • 内存映射机制(mmap)

    千次阅读 2018-11-15 01:04:21
    MMU位于CPU与物理内存之间,它包含从虚地址向物理内存地址转化的映射信息。当CPU引用一个内存位置时,MMU决定哪些页需要驻留(通常通过移位或屏蔽地址的某些位)以及转化虚拟页号到物理页号。 当某个进程读取磁盘...
    • 当CPU读取数据时,是由内存管理单元(MMU)管理的。MMU位于CPU与物理内存之间,它包含从虚地址向物理内存地址转化的映射信息。当CPU引用一个内存位置时,MMU决定哪些页需要驻留(通常通过移位或屏蔽地址的某些位)以及转化虚拟页号到物理页号。
      在这里插入图片描述
    • 当某个进程读取磁盘上的数据时,进程要求其缓冲通过read()系统调用填满,这个系统调用导致内核想磁盘控制硬件发出一条命令要从磁盘获取数据。磁盘控制器通过DMA直接将数据写入内核的内存缓冲区,不需要CPU协助。当请求read()操作时,一旦磁盘控制器完成了缓存的填写,内核从内核空间的临时缓存拷贝数据到进程指定的缓存中。
    • 用户空间是常规进程所在的区域,该区域执行的代码不能直接访问硬件设备。内核空间是操作系统所在的区域,该区域可以与设备控制器通讯,控制用户区域进程的运行状态。
      在这里插入图片描述
    • 内存映射文件技术是操作系统提供的一种新的文件数据存取机制,利用内存映射文件技术,系统可以在内存空间中为文件保留一部分空间,并将文件映射到这块保留空间,一旦文件被映射后,操作系统将管理页映射缓冲以及高速缓冲等任务,而不需要调用分配、释放内存块和文件输入/输出的API函数,也不需要自己提供任何缓冲算法。
    • 使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O 操作,这意味着在对文件进行处理时将不必再为文件申请并分配缓存,所有的文件缓存操作均由系统直接管理,由于取消了将文件数据加载到内存、数据从内存到文件的回写以及释放内存块等步骤,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。

    linux 内存映射机制

    void  *mmap(void  *start,  size_t length,  int prot,  int flags,  int fd,  off_t offsize)
    int  munmap(void *start,   size_t length)
    

    mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。 munmap执行相反的操作,删除特定地址区域的对象映射。
    在这里插入图片描述

    • 返回说明:

    成功执行时,mmap()返回被映射区的指针,munmap()返回0。失败时,mmap()返回MAP_FAILED(其为(void*)-1),munmap 返回-1。

    • 参数:

    start:映射区的开始地址。
    length:映射区的长度。
    prot:映射区域的保护方式。可以为以下几种方式的组合

    
        PROT_EXEC //页内容可以被执行
        PROT_READ //页内容可以被读取
        PROT_WRITE //页可以被写入
        PROT_NONE //页不可访问
    
    

    flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个以下位的组合体

    MAP_FIXED //使用指定的映射起始地址,如果由 start和len 参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。
    MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到 msync()或者munmap() 被调用,文件实际上不会被更新。
    MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个。
    MAP_DENYWRITE //这个标志被忽略。
    MAP_EXECUTABLE //同上
    MAP_NORESERVE //不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。
    MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。
    MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。
    MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。
    MAP_ANON //MAP_ANONYMOUS 的别称,不再被使用。
    MAP_FILE //兼容标志,被忽略。
    MAP_32BIT //将映射区放在进程地址空间的低 2GB,MAP_FIXED 指定时会被忽略。当前这个标志只在 x86-64平台上得到支持。
    MAP_POPULATE //为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞。
    MAP_NONBLOCK //仅和MAP_POPULATE 一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。
    
    

    fd:有效的文件描述词。
    offset:被映射对象内容的起点

    转载于:https://blog.csdn.net/aspirinvagrant/article/details/18991263

    展开全文
  • 内存映射 在 Linux操作系统中非常重要,因为其涉及到高效的跨进程通信 & 文件操作 今天,我将详细讲解操作系统中核心概念:内存映射 目录 1. 定义 关联 进程中的1个虚拟内存区域 & 1个磁盘上的...

    前言

    • 内存映射Linux操作系统中非常重要,因为其涉及到高效的跨进程通信 & 文件操作
    • 今天,我将详细讲解操作系统中核心概念:内存映射

    目录

    示意图


    1. 定义

    关联 进程中的1个虚拟内存区域 & 1个磁盘上的对象,使得二者存在映射关系

    1. 上述的映射过程 = 初始化该虚拟内存区域
    2. 虚拟内存区域被初始化后,就会在交换空间中换你来还去
    3. 被映射的对象称为:共享对象(普通文件 / 匿名文件)

    2. 作用

    若存在上述映射关系,则具备以下特征

    • 在多个进程的虚拟内存区域 已和同1个共享对象 建立映射关系的前提下
    • 若 其中1个进程对该虚拟区域进行写操作
    • 那么,对于 也把该共享对象映射到其自身虚拟内存区域的进程 也是可见的

    示意图如下

    1. 假设进程1、2的虚拟内存区域同时映射到同1个共享对象;
    2. 当进程1对其虚拟内存区域进行写操作时,也会映射到进程2中的虚拟内存区域

    示意图


    3. 实现过程

    • 内存映射的实现过程主要是通过Linux系统下的系统调用函数:mmap()
    • 该函数的作用 = 创建虚拟内存区域 + 与共享对象建立映射关系
    • 其函数原型、具体使用 & 内部流程 如下
    /**
      * 函数原型
      */
    void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
    
    /**
      * 具体使用(用户进程调用mmap())
      * 下述代码即常见了一片大小 = MAP_SIZE的接收缓存区 & 关联到共享对象中(即建立映射)
      */
      mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
    
    /**
      * 内部原理
      * 步骤1:创建虚拟内存区域
      * 步骤2:实现地址映射关系,即:进程的虚拟地址空间 ->> 共享对象
      * 注: 
      *    a. 此时,该虚拟地址并没有任何数据关联到文件中,仅仅只是建立映射关系
      *    b. 当其中1个进程对虚拟内存写入数据时,则真正实现了数据的可见
      */
    
    

    4. 特点

    • 提高数据的读、写 & 传输的时间性能
      1. 减少了数据拷贝次数
      2. 用户空间 & 内核空间的高效交互(通过映射的区域 直接交互)
      3. 用内存读写 代替 I/O读写
    • 提高内存利用率:通过虚拟内存 & 共享对象

    5. 应用场景

    Linux系统下,根据内存映射的本质原理 & 特点,其应用场景在于:

    1. 实现内存共享:如 跨进程通信
    2. 提高数据读 / 写效率 :如 文件读 / 写操作

    6. 实例讲解

    下面,我将详细讲解 内存映射应用在跨进程通信 & 文件操作的实例

    6.1 文件读 / 写操作

    • 传统的Linux系统文件操作流程如下

    示意图

    • 使用了内存映射的 文件读 / 写 操作

    示意图

    从上面可看出:使用了内存映射的文件读/写 操作方式效率更加高、性能最好!

    6.2 跨进程通信

    • 传统的跨进程通信

    示意图

    • 使用了内存映射的 跨进程通信

    示意图

    从上面可看出:使用了内存映射的跨进程通信 效率最高、性能最好!


    7. 总结

    • 本文全面讲解了 Linux操作系统中的内存映射

    • 下面我将继续讲解 编程开发的基础知识,感兴趣的同学可以继续关注carson_ho的微信公众号
      示意图
      示意图


    请点赞 / 评论点赞!因为你的鼓励是我写作的最大动力!

    展开全文
  • 内存映射的解释

    2017-07-07 15:25:11
    虚拟内存实际上是操作系统对于内存管理的一种方式,比如说,对每个程序而言,它的内存编址都从0x00到0xff,但是实际上,这些内存对应的物理地址,应用程序本身是无法知道的,在这里就可以理解成操作系统对内存管理的...
    这个问题很大。。。。我尽自己所能给你解释一下吧,如果你不能完全看懂,以后可以回头再翻翻来看。关于虚拟内存的事情,大概是这样的:
    首先你要明确什么是虚拟内存。虚拟内存实际上是操作系统对于内存管理的一种方式,比如说,对每个程序而言,它的内存编址都从0x00到0xff,但是实际上,这些内存对应的物理地址,应用程序本身是无法知道的,在这里就可以理解成操作系统对内存管理的一层抽象。
    比如,可能进程init的虚拟地址0x00对应了物理地址的0x10,而kthreadd的虚拟地址0x00对应物理地址0x20,etc.
    而且虚拟内存也是一种有效的进程间隔离的方式,极大的提升了进程的安全性和操作系统的稳定性,也就是我一个进程不管做什么,都是在它自己的地址空间里做的,不会影响到其他进程和OS。
    当然这是理想情况,实际上还有进程间通信啦之类,这就不在这个问题的范围之内了。
    而具体怎么把这些虚拟地址对应到物理地址上,这是操作系统做的事情,估计这个也就是你的问题。
    ----以上是背景1-----
    然后我要明确一下:地址总线4位的意思是说内存用4个bit位来表达地址,所以能够index的地址位就是2^0-2^4,也就是0x0到0xf,就是16个bit的内存空间。
    然后我们再来细化一下你的例子,就比方说在你的16bit的内存的机器上有1个OS,上面跑着2个程序。一般来说OS会保留地址的高位,比如11-15bit的位置,作为kernel space;然后0-10bit是user space。
    在以上的前提下,虚拟内存的效果是:在每一个程序看来,这个程序都有0x0到0xf的地址可以用,并且它们的0xb-0xf都是shared kernel space,然后0x0-0xa都是自己的user space,这样仿佛就有了32个bit的地址一样。这就是你所谓的是用虚拟地址可以使总的地址操作物理地址。至于os是怎么做到这点的,继续往下看。
    -----以上是背景2-----
    操作系统对每一个进程有一个进程控制块,叫PCB,Process Control Block,里边存储了每一个进程的进程信息,比如说寄存器,file descriptor,还有我们最关心的内存映射信息。每一个进程有一个递增的id号,叫pid,也就是Process IDentifier.
    -----以上是背景3-----
    进程间切换,也就是说,比如说你一个系统只有1个CPU,但是有两个进程要跑,而且要让我们看起来好像是两个进程同时在跑一样。为什么我要提到这个呢,后面继续看。
    -----以上是背景4-----
    好,现在来讲如何把虚拟地址映射到物理地址。从程序的角度来看,从malloc开始讲起,比如,在某一时刻,一个进程调用了malloc,在堆(heap)上申请了2bits的空间。实际上这个行为的流程是,程序调用malloc,进入内核模式之后,调用mmap,如果成功,操作系统会从物理地址上取一块2bits的内存,交给应用程序编入虚拟地址空间。更详细一点说,每个进程对内存管理是一个红黑树的结构,也就是说,在每一个进程的PCB,里维护了一颗红黑树,然后动态的将所有的新分配的内存加到这个红黑树里边,以保证程序对每一块内存的访问时间是差不多的。然后不知道你们教材中有没有提到页表(page table),页表也是PCB中的一项,你们教材中应该会对页表有详细的讲解,将如何对内存的地址进行换算,之类的。然后你要明确,页表实际上是红黑树的cache,这样可以加速程序对于常用的内存的访问速度。
    以上是操作系统对内存管理的一个大致概括,就是一块物理的内存如何映射成为一块虚拟的内存。
    我在背景2中说,两个程序都看到自己有16个bit的虚拟地址,总共有32bit,但是实际上硬件只有16bits,也就是说,不管你在红黑树和页表中怎么映射,一定会有冲突发生,比如,可能物理地址的0x02对应了进程1中的0x04,又在进程2的PCB中映射到了pid2的虚拟地址位0x06上。操作系统如何解决这个矛盾呢,首先在进程pid 1运行的时候,这个0x02对应的是pid1中的0x04;然后这个时候进程切换发生了,pid 2开始运行。当pid2需要用到它的0x04时,os发现0x02这个地址在pid1中也有映射,于是它就把0x02这个地址上的内容存到硬盘上的一个叫swap的空间内,然后把这个地址交给pid2使用。这样就达到了扩大虚拟地址的效果。
    但是这样做是有代价的,因为一旦这个page被swap出去,那么在pid1再来调用的时候会发生一系列的miss,从L1 cache miss到 L2 cache miss到L3 cache miss,然后页表miss,memory miss,会对程序的性能造成极大的影响。影响有多大呢,平均来说:
    L1 cache hit: 0.5ns
    L2 cache hit: 7ns
    主内存引用:100ns
    顺序从内存中读取1MB:250,000ns
    硬盘寻道:10,000,000ns
    从硬盘上顺序读取1MB:30,000,000ns
    所以你就可以知道这种行为是以极大的性能为代价的。
    ----讲完啦-----
    总的来说这个很大的话题,我刚才所写的东西的就是试图让你对虚拟内存这个东西有一个基本的概念,然后大致的了解内存是如何映射的。就我现在能想到的,对这个虚拟内存话题的讨论还包括多级页表,进程间隔离&通信以及memory fragment。
    展开全文
  • 内存映射的原理

    千次阅读 2018-05-09 16:26:54
    这不是问题,因为大多数程序只占用实际可用内存的一小部分。在将磁盘上的数据映射到进程的虚拟地址空间的时,内核必须提供数据结构,以建立虚拟地址空间的区域和相关数据所在位置之间的关联。例如,在映射文本文件时...

    原文:http://www.cnblogs.com/wuchanming/p/4823444.html

    由于所有用户进程总的虚拟地址空间比可用的物理内存大很多,因此只有最常用的部分才与物理页帧关联。这不是问题,因为大多数程序只占用实际可用内存的一小部分。

    在将磁盘上的数据映射到进程的虚拟地址空间的时,内核必须提供数据结构,以建立虚拟地址空间的区域和相关数据所在位置之间的关联。例如,在映射文本文件时,映射的虚拟内存区必须关联到文件系统的硬盘上存储文件内容的区域。如图所示:

    当然,给出的是简化的图,因为文件数据在硬盘上的存储通常并不是连续的,而是分布到若干小的区域。内核利用address_space数据结构,提供一组方法从后备存储器读取数据。例如,从文件系统读取。因此address_space形成了一个辅助层,将映射的数据表示为连续的线性区域,提供给内存管理子系统。

    按需分配和填充页称为按需调页法。它基于处理器和内核之间的交互,使用的各种数据结构如图所示:

    过程如下:

    CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步(如下图):

    首先,将给定一个逻辑地址(其实是段内偏移量,这个一定要理解!!!),CPU要利用其段式内存管理单元,先将为个逻辑地址转换成一个线程地址,

    其次,再利用其页式内存管理单元,转换为最终物理地址。

         

     这样做两次转换,的确是非常麻烦而且没有必要的,因为直接可以把线性地址抽像给进程。之所以这样冗余,Intel完全是为了兼容而已。

    • 进程试图访问用户地址空间中的一个内存地址,利用上面的线性地址去查找页表,确定对应的物理地址,但使用的页表无法确定物理地址(物理内存中没有关联页)
    • 处理器接下来触发一个缺页异常,发送到内核。
    • 内核会检查负责缺页区域的进程地址空间数据结构,找到适当的后备存储器,或者确认该访问实际上是不正确的(未映射,未使用)
    • 分配物理内存页,并从后备存储器读取所需数据填充。
    • 借助于页表将物理内存页并入到用户进程的地址空间,应用程序恢复执行。

    这些操作对用户进程是透明的。换句话说,进程不会注意到页是实际在物理内存中,还是需要通过按需调页加载。

     

    在整个过程中可能需要解决以下几个问题:

    1)系统如何感知进程当前所需页面不在主存(页表机制);
    2)当发现缺页时,如何把所缺页面调入主存(缺页中断机构);
    3)在置换页面时,根据什么策略选择欲淘汰的页面(置换算法)。

    页表机制

     

    状态位(中断位):标识该页是否在内存(0或1);
    访问位:标识该页面的近来的访问次数或时间(换出);
    修改位:标识此页是否在内存中被修改过;
    外存地址:记录该页面在外存上的地址,即(外存而非内存的)物理块号。

    缺页中断机制

    程序在执行时,首先检查页表,当状态位指示该页不在主存时,则引起一个缺页中断发生,其中断执行过程与一般中断相同:
    保护现场(CPU环境);
    中断处理(中断处理程序装入页面);
    恢复现场,返回断点继续执行。

    置换算法

    FIFO

    LRU

    LFU


    展开全文
  • 内存映射

    2012-10-26 14:38:32
    物理地址中很大一部分是留给内存条中的内存的,但也常被映射到其他存储器上 (如显存、BIOS等)。在程序指令中的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址线上。  物理...
  • 内存映射文件原理探索

    万次阅读 多人点赞 2010-09-17 14:38:00
    内存映射的过程中,并没有实际的数据拷贝,文件没有被载入内存,只是逻辑上被放入了内存,具体到代码,就是建立并初始化了相关的数据结构(struct address_space),这个过程有系统调用mmap()实现,所以建立内存...
  • linux内存映射(一)

    千次阅读 2019-12-24 16:19:32
    内存映射原理 由于所有用户进程总的虚拟地址空间比可用的物理内存大很多,因此只有最常用的部分才与物理页帧关联。这不是问题,因为大多数程序只占用实际可用内存的一小部分。在将磁盘上的数据映射到进程的虚拟...
  • 【Python学习之路】Numpy 内存映射

    万次阅读 2019-12-15 20:52:02
    内存映射 Numpy 有对内存映射的支持。 内存映射也是一种处理文件的方法,主要的函数有: memmap frombuffer ndarray constructor 内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,...
  • 内存映射文件原理

    万次阅读 2016-03-26 11:51:56
    一直都对内存映射文件这个概念很模糊,不知道它和虚拟内存有什么区别,而且映射这个词也很让人迷茫,今天终于搞清楚了。。。下面,我先解释一下我对映射这个词的理解,再区分一下几个容易混淆的概念,之后,什么是...
  • 尽管从JDK 1.4版本开始,Java内存映射文件(Memory Mapped Files)就已经在java.nio包中,但它对很多程序开发者来说仍然是一个相当新的概念。引入NIO后,Java IO已经相当快,而且内存映射文件提供了Java有可能达到的...
  • Linux内存映射: mmap

    万次阅读 2007-07-26 17:49:00
    Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明: 头文件: 原型: void *mmap(void *addr, size_t...
  • Linux 内存映射函数 mmap()函数详解

    万次阅读 多人点赞 2016-08-07 00:01:15
    mmap将一个文件或者其它对象映射内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。 头文件 函数原型 void* mmap...
  • Qt——文件映射

    千次阅读 2015-09-02 14:57:20
    概述:在处理数据量较大的文件时,往往需要使用文件映射技术,即虚拟内存。 通过文件映射之后,就可以像操作内存一样去直接操作文件。而不需要再调用文件读写方法了。原理:给磁盘上的文件分配地址,类似内存的地址...
  • 关于mmap内存映射的修改同步

    千次阅读 2012-03-28 22:06:21
    在看到《APUE》中第十四章的mmap内存映射才发现,当时自己是侥幸使用而已,没有遇到什么问题。 主要是没有考虑映射后的内存空间修改后,被映射的文件什么时候修改。在看了这一部分后,明白了很多。 以mmap...
  • 内存映射文件”可以将硬盘上的文件映射到虚拟地址空间,这样就不需要将所有东西都放入到页交换文件中,比如系统有许多程序同时运行时,如果将这些程序文件都加载到页交换文件中,页交换文件将会变得非常大。...
  • 操作系统:图文详解 内存映射

    千次阅读 2018-07-19 08:45:02
    操作系统:图文详解 内存映射   前言 内存映射 在 Linux操作系统中非常重要,因为其涉及到高效的跨进程通信 & 文件操作 今天,我将详细讲解操作系统中核心概念:内存映射 目录 示意图 1. 定义 ...
  • mongodb内存映射原理

    千次阅读 2019-07-05 15:15:01
    内存映射 mongodb非常吃内存,为啥这么吃内存呢,mongodb使用的是内存映射存储引擎,即Memory Mapped Storage Engine,简称MMAP,MMAP可以把磁盘文件的一部分或全部内容直接映射到内存,这样文件中的信息位置就会在...
  • Linux内核驱动之DDR3(二)内存映射

    千次阅读 2015-11-27 14:23:57
    内存映射的概念 上文中的内存寻址主要讲的是内存控制器如何去访问DDR3芯片基本存储单元 本文中的内存映射主要讲的是如何将内存控制器管理的DDR3芯片地址空间映射到SOC芯片为DDR3预留的地址范围。比如基于...
  • 不妨采用内存映射方式来写文件,达到高效。 我们这里采用mmap这种内存映射方法: 一、mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟...
  • mmap函数使用

    万次阅读 2008-01-22 17:29:00
    UNIX网络编程第二卷进程间通信...2、将特殊文件进行匿名内存映射,可以为关联进程提供共享内存空间;3、为无关联的进程提供共享内存空间,一般也是将一个普通文件映射到内存中。函数:void *mmap(void *start,size_t l
1 2 3 4 5 ... 20
收藏数 510,454
精华内容 204,181
关键字:

内存映射