Windows进程间通信--共享内存映射文件(FileMapping)--VS2012下发送和接收
之前以为两个互不相关的程序a.exe b.exe通信就只能通过网络,人家说可以通过发消息,我还深以为不然,对此,我表示万分惭愧。
之前课本上说的进程间通信,有共享内存、管道等之类的,但没有自己操刀写过程序的原理真心理解不了。
进程间通信的方法有很多,使用的条件也不太一样,有些必须同时在本机使用,有些可以远程,希望接下来的时间可以一个一个尝试,并弄懂。
言归正传,下面用共享映射文件的方式实现进程间通信,代码可以运行。但只是自己的学习过程,无过多实用价值,不足之处,请指正。
//-----------------------------------------------------------------------------------------------------------------------------------
1.浅理解
每个进程有自己独立的空间,一个进程无法访问其他进程的数据。就好像两个是互不干涉的个体,想让它们进行通信(交换数据),就必须有一段它们都可以访问到的空间,作为中间介质。
在计算机中,可以存放数据的地方分为内存和硬盘,进程是运行着的程序,肯定在内存当中。

为让进程A和进程B进行通信,它们都可以访问的空间可以是内存中它们以外的区域,或者是硬盘中的区域。
通过内存文件映射,则是将硬盘中的一个文件,映射到内存中,进程A,B都可以访问该内存(文件),达到交换数据的目的。
如右图是给用户的直接感觉,两个进程操作同一个物理文件,通过文件的读写,交换数据。
2.发送方(服务器)
个人理解,虽然共享内存都可以读写,也没有服务器和客户端的概念,但是,有一方需要创建这个文件,而另一方只需要打开这个文件。
所以,我将创建文件的一方,认为是服务器,而打开文件,进行读取的一方称为客户端。而事实上,服务器或者客户端都可以对文件进行读写,类似于网络编程中,都可以读写。
先贴代码,再解释
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#pragma warning(disable:4996) int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = CreateFile(TEXT("c:\zj.dat"),GENERIC_READ|GENERIC_WRITE,
0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile==NULL)
{
printf("create file error!");
return 0;
} // HANDLE hFile = (HANDLE)0xffffffff; //创建一个进程间共享的对象
HANDLE hMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE, 0,1024*1024,TEXT("ZJ"));
int rst = GetLastError();
if (hMap != NULL && rst == ERROR_ALREADY_EXISTS)
{
printf("hMap error\n");
CloseHandle(hMap);
hMap = NULL;
return 0;
} CHAR* pszText=NULL;
pszText = (CHAR*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,1024*1024);
if(pszText==NULL)
{
printf("view map error!");
return 0;
}
sprintf(pszText,"hello my first mapping file!\n"); //其实是向文件中(共享内存中)写入了
while(1)
{
printf(pszText);
Sleep(3000);
} getchar(); UnmapViewOfFile((LPCVOID)pszText);
CloseHandle(hMap);
CloseHandle(hFile); return 0;
}
1)创建一个文件 CreateFile
HANDLE hFile = CreateFile(...); 参数可参见MSDN,就是创建一般的文件,此处不详说。个人认为这个文件的目的,就是共享内存的实体(物理存在的)。
CreateFile(TEXT("c:\zj.dat"),GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
在C盘的确有文件zj.dat 该文件名可以随意取。
2)创建内存映射文件 CreateFileMapping
将上述真正存在的文件(物理文件) hFile映射成为一个虚拟的映射文件 hMap ,即将物理文件与虚拟文件绑定
HANDLE hMap = CreateFileMapping( hFile, NULL, PAGE_READWRITE, 0,1024*1024,TEXT("ZJ"));
参数解释: hFile: 是1)中对应的物理文件。如果hFile=NULL,即没有通过CreateFile创建一个实际存在的文件,有解释为创建一个进程间共享的对象。
个人认为也可能是在内存中开辟了一段空间,或者在硬盘上有一个默认文件。
NULL: 安全属性
PAGE_READWRITE: 可读可写
0, 1024*1024: 从物理文件的高0位到低1024*1024位映射成虚拟文件。(个人是这样理解的)
ZJ :是虚拟文件的名字,客户端读时也用这个名字,所以,可能这个名字是会在进程外部注册的。
3)加载内存映射文件 MapViewOfFile :映射成内存地址
将虚拟文件映射成内存地址,方便使用。即将文件与内存绑定,以后操作该内存其实就是操作该文件。
CHAR* pszText=NULL; //一个指针,不需要分配空间
pszText = (CHAR*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,1024*1024); //通过映射后,该指针就指向该文件。
参数解释:hMap:虚拟文件名
FILE_MAP_ALL_ACCESS:访问模式
0,0:从虚拟文件的哪个位置开始映射成内存
1024*1024: 映射多大的内存
4)使用内存,即使用文件
可以向这个内存(文件)读写数据了。
//写
sprintf(pszText,"hello my first mapping file!\n"); //语句本身的意思,是将句子写入字符串pszText中,而这个字符串并没有在程序中分配空间,即没有new
但这句话也不会报错。是因为该字符串地址指向了映射文件,即通过操作该指针,实际是操作了文件,句子写入了文件当中。
//读
printf(pszText); //语句本身是将字符串中的内容输出到屏幕上,该字符串中没有分配空间,也没有赋值。但通过映射为文件,可以将文件中的内容通过该指针输出到屏幕上。
注:个人理解,可以认为该指针pszText直接指向了硬盘空间。就是文件的操作符。
5)卸载映射 UnmapViewOfFile((LPCVOID)pszText);
6)关闭文件
CloseHandle(hMap); //关闭虚拟文件
CloseHandle(hFile); //关闭物理文件
3.接收方(客户端)
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,TRUE,TEXT("ZJ"));
if(hMap == NULL)
{
printf("open file map error!");
return ;
}
CHAR* pszText = NULL;
pszText = (CHAR*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,,,*);
if(pszText==NULL)
{
printf("map view error!\n");
return ;
}
printf(pszText); //从文件中读(共享内存)
sprintf(pszText,"second data!\n"); //写入
getchar();
UnmapViewOfFile(pszText);
CloseHandle(hMap);
hMap = NULL;
return ;
1)打开内存映射文件(虚拟文件)
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,TRUE,TEXT("ZJ"));
是通过内存映射文件名 ZJ 找到该文件的。
2)映射成内存 MapViewOfFile
和服务器中的一样。
3)使用内存
读写数据,此处写入数据后,从服务器中读出来的内容就改变了。可以证明,服务器客户端同时使用着同一个文件,文件是它们之间的一个通道,用来交换数据
4)关闭映射,关闭文件。同服务器
注:1)服务器和客户端必须同时为进程,即都在运行的时候,才可以交换数据。
虽然是通过物理文件,交互数据的,但是ZJ是虚拟文件的名字,该名字必须在两个进程中都能认识,才可以通过它来交互数据。
所以,如果,服务器先打开,写入文件后,关闭。 客户端,再打开文件,则CreateFileMap会失败,也无法进行文件映射了。
这是我犯的一个错误,不知道大家会不会理解,就是,像网络通信一样,必须双方都在,才可以通信。
当然客户端也可以通过CreateFile打开一个存在的文件 zj.dat ,再用CreateFileMap去映射,同样可以访问文件中的数据。
2)内存映射文件的机制是单纯的让访问文件变的简单。
就好像文件流fstream模拟了输入输出流iostream一样,操作文件,就像操作cout,cin一样方便。
同理,通过文件映射,操作文件就可以向操作内存一样方便。
只是将这个机制用于进程间通信时,才需要考虑一端发送,一端接收,同步问题等。
Windows进程间通信--共享内存映射文件(FileMapping)--VS2012下发送和接收的更多相关文章
- ython实现进程间的通信有Queue,Pipe,Value+Array等,其中Queue实现多个进程间的通信,而Pipe实现两个进程间通信,而Value+Array使用得是共享内存映射文件的方式,所以速度比较快
1.Queue的使用 from multiprocessing import Queue,Process import os,time,random #添加数据函数 def proc_write(qu ...
- 利用windows api共享内存通讯
主要涉及CreateFile,CreateFileMapping,GetLastError,MapViewOfFile,sprintf,OpenFileMapping,CreateProcess Cr ...
- C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转
原文:C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing ...
- C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped
节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作 ...
- C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案
C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...
- MemoryMappedFile 内存映射文件 msdn
http://msdn.microsoft.com/zh-cn/library/dd997372%28v=vs.110%29.aspx 内存映射文件 .NET Framework 4.5 其他版本 1 ...
- win32下进程间通信——共享内存
一.引言 在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...
- 【Windows核心编程】一个使用内存映射文件进行进程间通信的例子
进程间通信的方式有很多种,其底层原理使用的都是内存映射文件. 本文实现了Windows核心编程第五版475页上的demo,即使用内存映射文件来在进程间通信. 进程1 按钮[Create mappin ...
- 《windows核心编程》 17章 内存映射文件
内存映射文件主要用于以下三种情况: 系统使用内存映射文件载入并运行exe和dll,这大量节省了页交换文件的空间以及应用程序的启动时间 开发人员可以使用内存映射文件来访问磁盘上的数据文件.这使得我们可以 ...
随机推荐
- Codeforces Round 480 Div 2 光荣掉分记
痛 痛苦 痛苦啊. 越接近黄名想的越多了啊…… 都说了不要在意rating这破玩意了…… 没出E就算了,策略问题. 居然还FST了: FST个D就算了: FST个A算个**啊. 紧张的时候总会写出一些 ...
- Hadoop之Vmware通过仅Use Host-Only networking(使用主机网络)主机链接
Use Host-Only networking(使用主机网络)连接方式 [1]现在宿主机也就是本地电脑上设置IP地址 [2]设置虚拟机 Host-Only 方式 验证 宿 ...
- 3.1常用类(java学习笔记)包装类及日期类
一.包装类 java是一门面向对象的语言,秉承一切皆对象的思想. 可java中有一些基本数据类型并不是对象,有时可能需要将它们变为对象. 这时就需要用到我们的包装类了. 基本数据类型 包装类 int ...
- ios--计时器演示样例:一闪一闪亮晶晶(动画)
本演示样例实现的动画:UIView定时消失随后又闪现,即一闪一闪的动画 所採用的技术:定时器(NSTimer) + 动画(beginAnimations/commitAnimations) 详细实现步 ...
- ASP.NET MVC学习---(三)EF简单增删改查
那么现在我们已经大概从本质上了解了ef 巴拉巴拉说了一大堆之后 总算要进入ef的正题了 总在口头说也太不行了是吧~ 没错,现在要用ef进行一些实际的操作 做什么呢? 就做一个入门级的增删改查操作吧 废 ...
- 【共享单车】—— React后台管理系统开发手记:员工管理之增删改查
前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录.最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star. ...
- Java基础- super 和 this 解析
1. superkeyword表示超(父)类的意思.this变量代表对象本身. 2. super訪问父类被子类隐藏的变量或覆盖的方法.当前类假设是从超类继承而来的,当调用super.XX()就是调用基 ...
- 服务器和java程序的桥梁--jdbc/hibernate
现实的应用程序都是用户通过可视化界面发出指令从而修改数据库.本篇文章以Oracle为例,模拟怎么通过java代码实现数据库的增删改查. 新建一个Java项目,要建好桥梁,首先要拷入驱动Jar包放在项目 ...
- 向git库提交代码出现”There are no staged files"怎么办?
1.选择菜单“Window”->"Preference" 2.左边树菜单选择“Team”->"Git"->"Committing&q ...
- Android中IntentService详解
简单说,IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service ...