`
tiankefeng0520
  • 浏览: 146761 次
  • 性别: 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;
}

 

分享到:
评论

相关推荐

    通过文件映射,进程间通信demo

    本示例将详细介绍如何使用文件映射进行进程间通信,并通过具体的“进程间通信demo”来展示其实现过程。 首先,我们要理解什么是文件映射。在操作系统中,文件映射是将一个文件的内容映射到进程的虚拟地址空间中,...

    VC利用内存映射实现进程间通信

    在Windows操作系统中,进程间通信(IPC,Inter-Process Communication)是多个进程之间交换数据的重要方式。VC++作为Microsoft的C++开发环境,提供了多种实现IPC的方法,其中一种高效且低级别的方法就是利用内存映射...

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

    需要注意的是,使用内存映射文件进行进程间通信需要谨慎管理内存,确保在写入完成后正确地刷新缓冲区到文件,避免数据丢失。此外,由于文件被多个进程共享,必须同步对文件的访问,防止数据冲突。 总之,Java NIO的...

    利用内存映射文件实现的进程间的通信实例

    内存映射文件是一种在多个进程间共享数据的有效方式,它通过将文件映射到进程的虚拟地址空间来实现。在Windows操作系统中,这种技术被广泛使用,而在其他系统如Linux中,也有类似的概念,如mmap(memory map)函数。...

    文件映射-信号量-进程间通信

    本项目"文件映射-信号量-进程间通信"聚焦于两种主要的IPC技术:文件映射(Memory Mapped Files)和信号量(Semaphore)。下面将详细介绍这两个概念以及它们在实现进程间数据通信中的作用。 **文件映射** 文件映射是...

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

    ### 在VB中利用文件映射实现...通过上述示例可以看出,在VB中利用文件映射进行进程间通讯是非常灵活且高效的。这种方式不仅提高了数据交换的速度,还简化了编程模型,使得开发人员能够更加专注于业务逻辑的设计与实现。

    API 线程 文件映射 来实现 “通信”

    本项目探讨了如何利用API,特别是“文件映射”(Memory Mapped Files)和“事件”(Events)机制,来实现进程间的通信。下面我们将详细讨论这两个关键概念及其在实践中的应用。 首先,让我们深入了解文件映射。文件...

    进程间通信示例·内存映射文件方式

    它可能包括了创建、映射、读写和关闭文件映射的示例,可以帮助你理解并学习如何在实际项目中应用内存映射文件进行进程间通信。 在实际应用中,内存映射文件常用于多进程协作场景,如数据库缓存、日志记录、配置文件...

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

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

    C#实现进程间通讯(源码)

    压缩包文件"20230206 进程通讯"很可能包含了一些C#实现的进程间通信的源代码示例。这些示例可能涵盖了上述提到的几种通信方式,通过查看和学习这些源码,开发者可以更好地理解如何在实际项目中应用这些技术。 总之...

    Windows下进程间通信

    在给定的标题“Windows下进程间通信”和描述中,涉及了三种主要的IPC技术:内存文件映射、信号量和线程池。下面将详细阐述这些知识点。 1. 内存文件映射(Memory-Mapped Files): 内存文件映射是一种在多个进程...

    windows内存共享进程间通信

    在Windows操作系统中,进程间通信(IPC,Inter-Process Communication)是多个进程之间交换数据、协调工作的重要机制。"Windows内存共享"是其中一种常见的IPC技术,它允许不同的进程访问同一块内存区域,从而实现...

    VC实现进程之间的通讯

    在VC中,我们可以利用多种方法来实现进程间的通信,这些方法包括但不限于管道、共享内存、消息队列、套接字、命名管道、内存映射文件等。下面将详细介绍这些通信方式以及如何在VC中实现它们。 1. **管道**:管道是...

    VS2008代码式例:进程间通信,本人亲测OK

    本示例基于Visual Studio 2008(VS2008),提供了关于如何进行进程间通信的实践代码。下面,我们将深入探讨这个主题,并详细解析相关的知识点。 首先,让我们理解什么是进程间通信。在操作系统中,进程是程序的执行...

    磁盘文件映射内存映射

    内存映射文件(Memory-...综上所述,磁盘文件映射内存映射是现代操作系统中一种强大的技术,它在提升性能、简化编程模型和促进进程间通信方面都发挥了重要作用。理解和掌握这一技术对于优化应用程序的性能至关重要。

    进程间通讯 DEMO

    在Delphi7中,进程间通信可以通过多种方式实现,如管道(Pipes)、消息队列(Message Queues)、共享内存(Shared Memory)、套接字(Sockets)、命名管道(Named Pipes)、内存映射文件(Memory-Mapped Files)等。...

    进程间通信

    本文将深入探讨如何在Windows环境下实现进程间的有效通信,重点讲解内存映射文件这一通信方式。 内存映射文件(Memory-Mapped File)是一种高效且灵活的进程间通信方法。它将文件的内容映射到进程的虚拟地址空间,...

    Windows进程通信_文件内存映射

    在Windows操作系统中,进程间的通信(IPC,Inter-Process Communication)是实现不同进程间数据交换的重要手段。本文将深入探讨一种常见的IPC技术——文件内存映射(Memory-Mapped Files),并基于提供的`...

Global site tag (gtag.js) - Google Analytics