Windows进程间通讯(IPC)----内存映射文件
内存映射文件原理
内存映射文件是通过在虚拟地址空间中预留一块区域,然后通过从磁盘中已存在的文件为其调度物理存储器,访问此虚拟内存空间就相当于访问此磁盘文件了。
内存映射文件实现过程
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)----内存映射文件的更多相关文章
- QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开 本文地址:h ...
- High Performance Networking in Google Chrome 进程间通讯(IPC) 多进程资源加载
小结: 1. 小文件存储于一个文件中: 在内部,磁盘缓存(disk cache)实现了它自己的一组数据结构, 它们被存储在一个单独的缓存目录里.其中有索引文件(在浏览器启动时加载到内存中),数据文件( ...
- Android AIDL 进行进程间通讯(IPC)
编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...
- Windows进程间通讯(IPC)----共享内存
Windows中同一个EXE文件多次加载过程 Windows中EXE文件加载是基于内存映射文件的. 当EXE文件第一次被加载. 首先系统会先创建一个进程内核对象,并创建一个新的进程地址空间. 系统调用 ...
- Windows进程间通讯(IPC)----消息队列
消息队列 windows系统是通过消息驱动的,每移动一下鼠标,点击一下屏幕都会产生一个消息.这些消息会先被放在windows的一个系统消息队列(先进先出)中,windows系统会为每一个GUI线程创建 ...
- Windows进程间通讯(IPC)----WM_COPYDATA
WM_COPYDATA通讯思路 通过向其他进程的窗口过程发送WM_COPYDATA消息可以实现进程间通讯. 只能通过SendMessage发送WM_COPYDATA消息,而不能通过PostMessag ...
- windows 进程间通讯方法
Windows平台为我们提供了多种进程间通信的机制,主要包括:注册表方式.共享文件方式.共享内存方式.共享数据段.映射文件方式.管道方式. 剪贴板方式.消息方式.其中注册表方式需要增加注册表表项,而注 ...
- win32进程间通讯--共享内存
小白一枚,如有不对,请各位大神多多指教! 最近看了看win32进程间通讯.简单写了写利用共享内存实现进程间通讯 使用共享内存实现进程间通讯: 1.在WM_CREATE消息下创建文件映射内核对象 hMa ...
- 服务 远程服务 AIDL 进程间通讯 IPC
Activity aidl接口文件 package com.bqt.aidlservice; interface IBinderInterface { /* 更改文件后缀为[.aidl]去掉 ...
随机推荐
- 某SQL注入--报错注入payload
1.证明存在sql注入,根据这个报错语句,,有' 有% 2.payload 闭合语句 %' or (select extractvalue("anything",concat( ...
- Object类中的常用方法
1.getClass方法 源码: 功能: 返回此Object的运行时类. 什么是运行时类? 如上图所示,类从被加载到虚拟机内存开始,到卸载出内存为止,他的生命周期一共包含7个阶段.其中加载阶段虚拟机需 ...
- 在ASP.NET Core中用HttpClient(六)——ASP.NET Core中使用HttpClientFactory
到目前为止,我们一直直接使用HttpClient.在每个服务中,我们都创建了一个HttpClient实例和所有必需的配置.这会导致了重复代码.在这篇文章中,我们将学习如何通过使用HttpClient ...
- Echarts概述
1. Echarts概述 ECharts是百度开源的纯 Javascript 图表库,目前开源可以与highcharts相匹敌的一个图表库.支持折线图(区域图).柱状图(条状图).散点图(气泡图).K ...
- .Net Core 路由处理
用户请求接口路由,应用返回处理结果.应用中如何匹配请求的数据呢?为何能如此精确的找到对应的处理方法?今天就谈谈这个路由.路由负责匹配传入的HTTP请求,将这些请求发送到可以执行的终结点.终结点在应用中 ...
- VS2019 自定义项目模板
前言: 使用"宇宙最强IDE"开发项目时,都需要根据不同情况选择一个项目模板,来满足开发需求:如下 VS为我们提供了基础的项目模板,但现有项目模板未包含基础功能如:日志输出.审计日 ...
- 一文带你剖析LiteOS互斥锁Mutex源代码
摘要:多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,只能被独占使用.LiteOS使用互斥锁来避免这种冲突,互斥锁是一种特殊的二值性信号量,用于实现对临界资源的独占 ...
- Mokito 单元测试与 Spring-Boot 集成测试
Mokito 单元测试与 Spring-Boot 集成测试 版本说明 Java:1.8 JUnit:5.x Mokito:3.x H2:1.4.200 spring-boot-starter-test ...
- 6. linux 专业词汇
什么是交换分区? 交换分区是一个特殊的分区,他的作用相当于windows下的虚拟内存,这个分区的大小一般设置为物理内存的两倍. 什么是Grub? Grub是一个系统引导工具,通过它可以加载内核,从而引 ...
- Java面向对象7大设计原则
目录 单一职责原则 SRP 开闭原则 OCP 里氏替换原则 LSP 依赖倒置原则 DIP 接口隔离原则 ISP 组合复用原则 CRP 迪米特法则 LOD 单一职责原则 SRP 一个类只有一个引起修改变 ...