`
tiankefeng0520
  • 浏览: 143251 次
  • 性别: Icon_minigender_1
  • 来自: 长春
社区版块
存档分类
最新评论

应用文件映射进行进程间通讯

 
阅读更多

文件映射解释:

(摘抄)内存映射文件用来保留一个地址空间,并提交物理存储器。早期的内存映射文件并不是提交物理内存供调用者使用,而是提交永久存储器(外存)上的文件数据。当然操作系统会为永久存储器保留一个读缓冲区,这样读取文件数据就快多了。内存映射文件的特点使它很适合于加载EXE或DLL文件。这样可以节省内存又减少了加载所需时间。还可以使用它来映射大容量的文件,这样就不必在读取文件数据前设置很大的缓冲区。另外内存映射文件常用于进程间通信,也是进程间通信的主要手段,其它进程之间通信机制都是基于内存映射文件来实现。为了更快的在进程之间通信,现在的内存映射文件也可以提交物理内存,这样内存映射文件既可以提交物理内存又可以提交文件

 

应用文件映射进行进程间通信

原来来内存映射文件只映射类似磁盘一类的存储器上的文件。而为了更快速地在进程之间通信,内存映射文件还可以提交物理内存。实现方法是通过访问同一个内存映射文件对象(映射到物理内存),两个进程或多个进程就能够访问到同一块物理内存设进程。

 

假设进程A和进程B需要通信,那么进程A需要先创建一个内存映射文件(之前不必调用CreateFileForMapping函数来创建文件,因为不需要创建文件)。这个内存映射文件可以是在永久存储器中,也可以是在内存中。为了减小通信时间,最好提交物理内存。

1.进程A在调用CreateFileMapping函数时,参数1指定为INVALID_HANDLE_VALUE,这表示这个内存映射文件对象将要把物理内存提交到地址空间中。最后一个参数一定要指定一个名字。

2.进程B也同样调用CreateFileMapping函数,而且参数相同。内核会根据名字来判断是否已经存在一个内存映射文件对象,如果创建了就返回原来的对象的句柄。

3.获得地址空间指针 
    MapViewOfFile()
    如果需要进行文件写入, 可以通过类型转换直接对于内存地址进行赋值, 比如:  memcpy( lpAddress, lpBuf, ....)     如果是读取操作, 将参数顺序调整一下


4.卸载内存映射文件地址指针 
    UnmapViewOffFile()

 5.关闭内存映射文件 
   CloseHandle()

 

下面这个例子写进程加载一个位图并将数据写到内存映射文件中,读进程从内存映射文件读取数据并生成新位图。

写进程:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include "FileHandler.h"

using namespace std;

typedef struct
{
	long  size;
	long  bufferAdd;

}SharedData;

SharedData *lpData ;
HANDLE hMemoryMap;

void FreeMemory()
{
	if(lpData)
	{
		::UnmapViewOfFile(lpData);
		lpData=NULL;

	}
	if(hMemoryMap)
	{
		CloseHandle(hMemoryMap);
		hMemoryMap = NULL;
	}
}

BYTE* CAlloc(WCHAR* name, long size)
{
	FreeMemory();

	BYTE* addr;
	hMemoryMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, size, name);
	if (hMemoryMap != NULL)
	{
		addr = (BYTE *)MapViewOfFile(hMemoryMap, FILE_MAP_WRITE, 0, 0, 0);
		if (addr == NULL)
		{
			CloseHandle(hMemoryMap);
			hMemoryMap = NULL;
			return NULL;
		}
		if(IsBadWritePtr(addr,size)!=FALSE)
		{
			::UnmapViewOfFile(addr);
			addr = NULL;
			::CloseHandle(hMemoryMap);
			hMemoryMap = NULL;
		}
	}
	return addr;
}

int _tmain(int argc, _TCHAR* argv[])
{

	hMemoryMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, 64, L"DataMap");
	if (hMemoryMap != NULL)
	{
	lpData = (SharedData *)MapViewOfFile(hMemoryMap, FILE_MAP_WRITE, 0, 0, 0);
		if (lpData == NULL)
		{
			CloseHandle(hMemoryMap);
			hMemoryMap = NULL;
		}
	}

	FileHandler *h=new FileHandler;
	FileInfo file=h->ReadFile("file/Butterfly2.bmp");
	lpData =(SharedData *)CAlloc( L"DataMap",sizeof(long)*2+file.size);
	lpData->size=file.size;
	lpData->bufferAdd=(long)(lpData+sizeof(long)*2);
	void * dst=(void *)(lpData+sizeof(long)*2);
	memcpy(dst,file.buffer,file.size);
        delete file.buffer;
        file.buffer=NULL;

        std::cout<<"\nwaiting.......";
        Sleep(-1);
 return 0;
}

 

读进程:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include "FileHandler.h"
using namespace std;

typedef struct
{
    long   size;
    long   bufferAdd;
}SharedInData;

int _tmain(int argc, _TCHAR* argv[])
{
    SharedInData *lpData ;
    HANDLE hMemoryMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, 4096, L"DataMap");
    if (hMemoryMap != NULL)
    {
        lpData =(SharedInData *) MapViewOfFile(hMemoryMap, FILE_MAP_READ, 0, 0, 0);
        if (lpData == NULL)
        {
            CloseHandle(hMemoryMap);
            hMemoryMap = NULL;
        }
    }

    FileHandler *file=new FileHandler;
    file->WriteFile("bitmap.bmp",(char*)lpData->bufferAdd,lpData->size);
    Sleep(-1);
    return 0;
}

 

 

文件处理类:

#include "stdafx.h"
#include "FileHandler.h"
using namespace std;

/*************************************************************************/
/*ofstream: 写操作(输出)的文件类 (由ostream引申而来) 
/*ifstream: 读操作(输入)的文件类(由istream引申而来) 
/*fstream: 可同时读写操作的文件类 (由iostream引申而来) 

ios::in 为输入(读)而打开文件 
ios::out 为输出(写)而打开文件 
ios::ate 初始位置:文件尾 
ios::app 所有输出附加在文件末尾 
ios::trunc 如果文件已存在则先删除该文件 
ios::binary 二进制方式 

seekg ( off_type offset, seekdir direction );
seekp ( off_type offset, seekdir direction );
使用这个原型可以指定由参数direction决定的一个具体的指针开始计算的一个位移(offset)。它可以是:

ios::beg 从流开始位置计算的位移 
ios::cur 从流指针当前位置开始计算的位移 
ios::end 从流末尾处开始计算的位移 


/*************************************************************************/
FileHandler::FileHandler()
{

}

FileHandler::~FileHandler()
{

}

FileInfo FileHandler::ReadFile(char* filename)
{
	FileInfo info;
	char * buffer;        
	long size;        
	ifstream file (filename, ios::in|ios::binary|ios::ate);       
	size = file.tellg();       
	file.seekg (0, ios::beg);      
	buffer = new char [size];   
	
	file.read (buffer, size);      
	file.close();     
	info.size=size;
	info.buffer=buffer;
	//buffer[size]='\0';
	cout << "the complete file is in a buffer:"<<size;   
	return info;
}

bool FileHandler::WriteFile(char* filename,char * buffer,int length)
{


	ofstream file (filename, ios::out|ios::binary|ios::trunc); 
	file.write(buffer,length);
	file.close();
	return true;

}
long FileHandler::GetFileSize(char* filename)
{
	int size=0;
	ifstream file (filename, ios::in|ios::binary|ios::ate);       
	size = file.tellg();       

	file.close(); 
	return size;
}

 

分享到:
评论

相关推荐

    Java NIO 应用使用内存映射文件实现进程间通信

    Java NIO 应用 -- 使用内存映射文件实现进程间通信

    在VB中用文件映射来进行进程通讯

    当我们用VB开发应用系统时,可能涉及多进程问题。在多个应用程序之间交换数据,我们自然会想到磁盘文件,但这种方法在实时系统中...幸运的是,Windows提供了几种高效的进程间交换数据的机制,如管道,邮路和文件映射。

    C++ 可以解决64位程序调用32位库、双向信道跨进程间通信的文件映射处理类源码

    1初始化文件映射对象 2同步 3获取文件映射对象的映射视图 4释放文件映射对象的映射视图 5释放文件映射对象 源码包含了封装的功能模块类以及测试类, 全部源码都可以用VS2020编译通过,请放心使用! 友情提示,为了...

    《UNIX网络编程 第2版. 第2卷, 进程间通信(中文版)》(W·Richard Stevens[美] 著)

    良好的进程间通信(IPC)机制是提高UNIX程序性能的关键。本书全面深入地讲解了各种进程间通信形式,包括消息传递、同步、共享内存及远程调用(RPC)。书中包含了大量经过优化的源代码,帮助读者加深理解。这些源代码...

    UNIX网络编程 第2卷 进程间通信

    良好的进程间通信(IPC)机制是提高UNIX程序性能的关键。本书全面深入地讲解了各种进程间通信形式,包括消息传递、同步、共享内存及远程调用(RPC)。书中包含了大量经过优化的源代码,帮助读者加深理解。这些源代码...

    进程之间通信例子,包含接收端和发送端

    5)管道(Pipe):用于设置应用程序间的一条永久通讯通道,通过该通道可以象自己的应用程序访问一个平面文件一样读写数据。 6)邮件槽(Mailslots):广播式通信,在32系统中提供的新方法,可以在不同主机间交换...

    Windows应用程序捆绑核心编程光盘代码

    4.4 如何用Windows套接字进行进程间通信 90 4.4.1 套接字分类 90 4.4.2 流式套接字编程流程 91 4.4.3 套接字调用基本函数 92 4.4.4 Winsock程序设计 95 4.4.5 一个通用套接字类 96 4.4.6 套接字服务器端与...

    《Visual C++范例大全》随书光盘 第十一章

    第11章 实例257——使用Win32 API创建、销毁线程(控制进度条) 实例258——创建MFC用户界面线程 实例259——创建MFC... 实例276——通过内存映射实现进程间的数据交换 实例277——通过消息机制实现进程间的通信

    《Delphi 深度编程及其项目应用开发》PDF书及代码

    2.2.2 利用内存映射文件实现进程间通讯 2.3 TThread对象 2.3.1 线程的创建 2.3.2 线程的挂起和恢复 2.3.3 线程的终止 2.3.4 与VCL同步 2.4 线程同步 2.4.1 临界区(CriticalSection) 2.4.2 互斥(Mutex) 2.4.3 信号量...

    MFC消息映射机制的剖析

    从实际应用入手,由浅入深、循序渐进地讲述Windows程序内部运行机制、MFC框架、文本、菜单、对话框、文件操作、网络编程、进程间通信、ActiveX控件、动态链接库、HOOK编程等多个主题。本书不同于一般的讲述VC++使用...

    InterJVM_NodesCommunication:应用程序在不同机器之间进行通信JVM

    服务器之间的 JVM/进程间通信 此应用程序需要在节点之间进行协调,并确保其中一个且只有一个执行 System.out.println("We are started!") 此应用程序在不同节点/机器上的不同进程会从内存映射文件(status.txt)并...

    vc.rar_9-12 VC_MFC与网络通信_mfc activex_vc dll_vc 生成 dll 文件

    第1课 Windows程序运行原理及程序编写流程 3 第2课 类的编写与应用 5 第3课 讲述MFC AppWizard的原理与MFC程序框架的剖析 6 ...第17课 进程间通信 47 第18课 ActiveX编程 56 第19课 DLL编程 58 第20课 钩子与数据库编程

    《Windows网络编程技术》高清PDF版+随书源码

    单机资源共享的应用编程2.1 进程间通信2.1.1 进程间通信应用实例及概念2.1.2 进程的创建与终止2.1.3 内存文件映射2.2 多线程通信2.2.1 多线程应用实例及概念2.2.2 线程的创建、挂起、激活和终止2.2.3 线程的优先级...

    Delphi深度编程技术

    2.2.2 利用内存映射文件实现进程间通讯 2.3 TThread对象 2.3.1 线程的创建 2.3.2 线程的挂起和恢复 2.3.3 线程的终止 2.3.4 与VCL同步 2.4 线程同步 2.4.1 临界区(CriticalSection) 2.4.2 互斥(Mutex) ...

    《Android系统源代码情景分析》

    5.3 Binder进程间通信应用实例 5.4 Binder对象引用计数技术 5.4.1 Binder本地对象的生命周期 5.4.2 Binder实体对象的生命周期 5.4.3 Binder引用对象的生命周期 5.4.4 Binder代理对象的生命周期 5.5 ...

    WINDOWS网络编程技术.pdf

    单机资源共享的应用编程2.1 进程间通信2.1.1 进程间通信应用实例及概念2.1.2 进程的创建与终止2.1.3 内存文件映射2.2 多线程通信2.2.1 多线程应用实例及概念2.2.2 线程的创建、挂起、激活和终止2.2.3 线程的优先级...

    嵌入式\(高校应用案例)北航软件学院

    Linux进程间的通信(一):管道通信;Linux进程间的通信(二):信号;Linux进程间的通信(三):消息队列与共享内存 ZKQ090105 FPGA1/CPLD EDA技术简介以及CPLD/FPGA 基础知识,QuartusII软件入门;硬件描述语言( ...

    Android系统源代码情景分析-罗升阳-源码

    5.3 Binder进程间通信应用实例 5.4 Binder对象引用计数技术 5.4.1 Binder本地对象的生命周期 5.4.2 Binder实体对象的生命周期 5.4.3 Binder引用对象的生命周期 5.4.4 Binder代理对象的生命周期 5.5 Binder...

Global site tag (gtag.js) - Google Analytics