内存映射文件原理

内存映射文件是通过在虚拟地址空间中预留一块区域,然后通过从磁盘中已存在的文件为其调度物理存储器,访问此虚拟内存空间就相当于访问此磁盘文件了。

内存映射文件实现过程

HANDLE hFile = CreateFile(...);                              //创建文件对象
HANDLE hFileMapping = CreateFileMapping(hFile, ...); //创建文件映射对象
MapViewOfFile(hFileMapping, ...); //在虚拟地址空间上建立映射 //其他操作 UnmapViewOfFile(hFileMapping); //撤销在虚拟地址空间上的映射
CloseHandle(hFileMapping); //关闭文件映射对象句柄
CloseHandle(hFile); //关闭文件对象句柄

以上代码就是建立内存映射文件的基本思路,注意在MapViewOfFile()在虚拟地址空间上建立映射的时候磁盘中的文件并没有加载到内存中,只有当访问此虚拟地址空间时会往实际物理内存中寻找对应数据,如果没有就发生缺页中断从而让磁盘中的文件加载到物理内存中。

内存映射文件实现进程间通讯

以磁盘中的文件为物理存储器的内存映射文件

通过在多个不同的进程中使用同一个文件映射对象在各自的进程空间中建立映射。

使用写时复制

所谓的写时复制是指,当在虚拟地址空间上建立文件映射后,如果对此地址空间进行写操作时,其不直接更改对应在物理内存中的数据,而是将对应物理内存中的内存页复制到虚拟内存的页交换文件中,然后修改页交换文件的内容。(也就是不改变磁盘中的文件)

//进程A
HANDLE hFile = CreateFile(...);
HANDLE hFileMapping = CreateFileMapping(hFile, , PAGE_WRITECOPY, , , TEXT("MapFile")); //PAGE_WRITECOPY写时复制标志
LPVOID lpAddress = MapViewOfFile(hFileMapping, , FILE_MAP_COPY, ...); //FILE_MAP_COPY写时复制标志 UnmapViewOfFile(hFileMapping);
CloseHandle(hFileMapping);
CloseHandle(hFile); //进程B
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, TEXT("MapFile"));
LPVOID lpAddress = MapViewOfFile(hFileMapping, , FILE_MAP_COPY, ...); UnmapViewOfFile(hFileMapping);
CloseHandle(hFileMapping);

上述代码就是设置了写时复制标志,当进程A和进程B修改自己进程空间对应映射地址的内存时,其实际是会修改对应的(A修改A的,B修改B的)页面交换文件的数据,并没有修改对应的物理内存中的数据所以不能实现进程间通讯。

不使用写时复制

不使用写时复制也就是不使用PAGE_WRITECOPY和FILE_MAP_COPY标志,对地址空间进行写操作时,其直接更改对应在物理内存中的数据。因为在不同进程中是通过同一文件映射对象建立的映射,所以其修改的是同一物理内存,可以实现进程间通讯。

//进程A
HANDLE hFile = CreateFile(...);
HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, TEXT("MapFile"));
LPVOID lpAddress = MapViewOfFile(hFileMapping, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); UnmapViewOfFile(hFileMapping);
CloseHandle(hFileMapping);
CloseHandle(hFile); //进程B
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, TEXT("MapFile")); //权限为FILE_MAP_ALL_ACCESS
LPVOID lpAddress = MapViewOfFile(hFileMapping, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); UnmapViewOfFile(hFileMapping);
CloseHandle(hFileMapping);

上述代码在没有使用写时复制标志,所以当A/B进程修改自己进程中的文件映射时实际就是在修改同一块物理内存的数据,可以实现进程间通讯。

同时注意:上述代码是利用给文件映射对象句柄命名从而跨进程使用句柄的,还可以使用句柄继承和句柄复制来实现跨进程共享句柄。

以页交换文件为物理存储器的内存映射文件

因为以磁盘中已存在的文件作为物理存储器的内存映射文件在实现进程间通讯时是通过更改文件中的数据通信的,结果是会使更改的数据保存到文件中。为了避免更改文件,Windows实现了利用虚拟内存的页交换文件为物理存储器的内存映射文件实现进程间通讯,其通过更改页交换文件实现通信,所以不会更改任何磁盘文件。

//进程A
HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, TEXT("MapFile"));
LPVOID lpAddress = MapViewOfFile(hFileMapping, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); UnmapViewOfFile(hFileMapping);
CloseHandle(hFileMapping); //进程B
HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, TEXT("MapFile"));
LPVOID lpAddress = MapViewOfFile(hFileMapping, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); UnmapViewOfFile(hFileMapping);
CloseHandle(hFileMapping);

注意:CreateFileMapping第一个参数为INVALID_HANDLE_VALUE,其指定的内存映射文件的大小需要时1024的倍数。

Windows进程间通讯(IPC)----内存映射文件的更多相关文章

  1. QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开     本文地址:h ...

  2. High Performance Networking in Google Chrome 进程间通讯(IPC) 多进程资源加载

    小结: 1. 小文件存储于一个文件中: 在内部,磁盘缓存(disk cache)实现了它自己的一组数据结构, 它们被存储在一个单独的缓存目录里.其中有索引文件(在浏览器启动时加载到内存中),数据文件( ...

  3. Android AIDL 进行进程间通讯(IPC)

    编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...

  4. Windows进程间通讯(IPC)----共享内存

    Windows中同一个EXE文件多次加载过程 Windows中EXE文件加载是基于内存映射文件的. 当EXE文件第一次被加载. 首先系统会先创建一个进程内核对象,并创建一个新的进程地址空间. 系统调用 ...

  5. Windows进程间通讯(IPC)----消息队列

    消息队列 windows系统是通过消息驱动的,每移动一下鼠标,点击一下屏幕都会产生一个消息.这些消息会先被放在windows的一个系统消息队列(先进先出)中,windows系统会为每一个GUI线程创建 ...

  6. Windows进程间通讯(IPC)----WM_COPYDATA

    WM_COPYDATA通讯思路 通过向其他进程的窗口过程发送WM_COPYDATA消息可以实现进程间通讯. 只能通过SendMessage发送WM_COPYDATA消息,而不能通过PostMessag ...

  7. windows 进程间通讯方法

    Windows平台为我们提供了多种进程间通信的机制,主要包括:注册表方式.共享文件方式.共享内存方式.共享数据段.映射文件方式.管道方式. 剪贴板方式.消息方式.其中注册表方式需要增加注册表表项,而注 ...

  8. win32进程间通讯--共享内存

    小白一枚,如有不对,请各位大神多多指教! 最近看了看win32进程间通讯.简单写了写利用共享内存实现进程间通讯 使用共享内存实现进程间通讯: 1.在WM_CREATE消息下创建文件映射内核对象 hMa ...

  9. 服务 远程服务 AIDL 进程间通讯 IPC

    Activity aidl接口文件 package com.bqt.aidlservice;  interface IBinderInterface {     /* 更改文件后缀为[.aidl]去掉 ...

随机推荐

  1. JVM笔记--如果你写JVM,最需要考虑的重要结构是什么?

    开局一张图,前面已经从每一部分解析过JVM的内存结构了,现在按照顺序来分析: 整体上来看:类文件从类加载子系统,加载完成之后,主要存放在方法区(JRockit和H9没有方法区,这里指的是HotSpot ...

  2. Shuffle Card HDU - 6707

    题目链接:https://vjudge.net/problem/HDU-6707 题意:给你一个数组a[ ](a[1]=1,a[2]=2.....a[n]=n),然后m次操作,每次把那个数拿到最前面去 ...

  3. c++ 反汇编 构造函数和析构函数

    构造函数和析构函数出现的时机 局部对象 109: // 局部对象定义调用构造函数 110: 111: CNumber Number; 00C8A37D 8D 4D EC lea ecx,[Number ...

  4. [倍增]luogu P4155 [SCOI2015]国旗计划

    题面 https://www.luogu.com.cn/problem/P4155 问在环上最少取多少个区间能完全覆盖环 分析 首先发现是环,先把端点变为2n方便处理,注意离散化 其次要删去贡献不如其 ...

  5. Android学习之CoordinatorLayout+FloatingActionButton+Snackbar

    CoordinatorLayout •简介 CoordinatorLayout 协调布局,可以理解为功能更强大的 FrameLayout 布局: 它在普通情况下作用和 FrameLayout 基本一致 ...

  6. 【JVM进阶之路】八:性能监控工具-命令行篇

    定位问题的时候,知识.经验是关键基础,数据是依据,工具是运用知识处理数据的手段. 在实际的故障排查.性能监控中,常常是操作系统的工具和Java虚拟机的工具结合使用. 1.操作系统工具 1.1.top: ...

  7. MyBatis-Plus Generator自定义模板

    相信大家在开发过程中,应该都用过Mybatis-Plus的Generator,但是可能没有自定义过模板并使用. 每个项目都应该有一个从Controller层到Mapper层的通用模板,来去掉哪些简单的 ...

  8. [状压DP]车

    车 车 车 题目描述 在 n ∗ n n*n n∗n( n ≤ 20 n≤20 n≤20)的方格棋盘上放置 n n n个车(可以攻击所在行.列),有些格子不能放,求使它们不能互相攻击的方案总数. 输入 ...

  9. [Fundamental of Power Electronics]-PART II-7. 交流等效电路建模-7.4 规范电路模型

    7.4 规范电路模型 在讨论了推导开关变换器交流等效电路模型的几种方法后,让我们先停下来,说明下这些结果.所有的在 CCM下以PWM工作的DC-DC变换器都具有相似的基本功能.首先,他们在理想情况下, ...

  10. java面试-阻塞队列

    一.阻塞队列 当阻塞队列是空,从队列中获取元素的操作会被阻塞 当阻塞队列是满,往队列中添加元素的操作会被阻塞 二.为什么用,有什么好处? 我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为 ...