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

使用内存映射文件的一般流程:

VC中用内存映射文件处理大文件(图二)

     由于内存映射文件的一致性,即系统保证在同一文件映射对象的多个视图间保持一致。这可以作为进程通讯的基础,而且在Windows上,同一台机器上共享数据的最底层机制都是内存映射文件。

    许多应用程序会在运行过程中创建一些数据,并需要将这些数据传输给其他进程,或与其他进程共享这些数据。如果为了共享数据而必须让应用程序在磁盘上创建数据文件并把数据保存在文件中,那将非常不方便。
    Microsoft意识到了这一点,并加入了相应的支持,让系统能够创建以页交换文件为后备存储器的内存映射文件,这样就不需要用磁盘上专门的文件来作为后备存储器了。这种方法和为磁盘文件创建内存映射文件的方法几乎完全相同,甚至更简单。一方面,由于不必创建或打开一个专门的磁盘文件,因此不需要调用CreateFile。我们只需要像原来那样调用CreateFileMapping,并将INVALID_HANDLE_VALUE作为hFile参数传入。这告诉系统我们创建的文件映射对象的物理存储器不是磁盘上的文件,而是希望系统从页交换文件中调拨物理存储器。所需分配的存储器大小由CreateFileMapping的dwMaximumSizeHigh和dwMaxinumSizeLow参数决定。
     这样,内存映射文件可以分为两种:
     一种是普通的文件,它需要一个普通的文件句柄,用于快速的读写文件,这种文件的数据在进程退出后会保存在硬盘上,所以进程在下次运行时可以得到之前的数据;
     另一种是页文件,当创建内存映射文件的时候传入无效的句柄,这时会把页文件当作临时的共享存储空间,当进程退出后这些数据是不会存储下来的。因为共享内存通常只关注执行期间的数据共享,所以一般是使用这种内存映射文件。
    一旦创建了文件映射对象,并把一个视图映射到了进程的地址空间中,我们就可以像使用任务内存区域一样使用它了。如果想要和其他进程共享数据,那么可以在调用CreateFileMapping的时候将一个以0为终止符的字符串作为pszName参数传入。这样其他想要访问共享数据的进程就能够以同一个名称为参数来调用CreateFileMapping或OpenFileMapping。
    当一个进程不再需要访问文件映射对象的时候,应该调用CloseHandle。当所有句柄都已关闭的时候,系统会从页交换文件中收回所有已调拨的存储器。

     下面是进程通讯代码及详细注释:

//进程1先启动,用于发送数据,即将数据写入视图
#include <windows.h>  
#include <stdio.h>  
#include <conio.h>  
#include <tchar.h>  

#define BUF_SIZE 256  
TCHAR szName[] = TEXT("MyFileMappingObject");  
TCHAR szMsg[] = TEXT("Message from first process.");  

int _tmain()  
{  
    HANDLE hMapFile;  
    LPCTSTR pBuf;  
	
    hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,  
		NULL,  
		PAGE_READWRITE,  
		0,  
		BUF_SIZE,  
		szName);  
	
    if (hMapFile == NULL)  
    {  
        _tprintf(TEXT("Could not create file mapping object (%d).\n"),  
            GetLastError());  
        return 1;  
    }  
    pBuf = (LPTSTR)MapViewOfFile(hMapFile,  
		FILE_MAP_ALL_ACCESS,  
		0,  
		0,  
		BUF_SIZE);  
	
    if (pBuf == NULL)  
    {  
        _tprintf(TEXT("Could not map view of file (%d). \n"),  
            GetLastError());  
        CloseHandle(hMapFile);  
        return 1;  
    }  
	
    CopyMemory((void*)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR))); //发送数据 
    _getch();  
	
    UnmapViewOfFile(pBuf);  
    CloseHandle(hMapFile);  
	
    return 0;  
} 

//进程2后启动,用于接收数据,即读取视图的数据
#include <windows.h>  
#include <stdio.h>  
#include <conio.h>  
#include <tchar.h>  
#pragma comment(lib, "user32.lib")  

#define BUF_SIZE 256  
TCHAR szName[] = TEXT("MyFileMappingObject");  

int _tmain()  
{  
    HANDLE hMapFile;  
    LPCTSTR pBuf;  
	
    hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,  
		FALSE,  
		szName);  
    if (hMapFile == NULL)  
    {  
        _tprintf(TEXT("Could not open file mapping object (%d). \n"),  
            GetLastError());  
        return 1;  
    }  
	
    pBuf = (LPTSTR)MapViewOfFile(hMapFile,  
		FILE_MAP_ALL_ACCESS,  
		0,  
		0,  
		BUF_SIZE);  
	
    if (pBuf == NULL)  
    {  
        _tprintf(TEXT("Could not map view of file (%d).\n"),  
            GetLastError());  
        CloseHandle(hMapFile);  
        return 1;  
    }  

    MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);  //接收数据并显示

    UnmapViewOfFile(pBuf);  
    CloseHandle(hMapFile);  
	
    return 0;  
}  

注意:

在这儿我们又必须提醒一下一个隐含的易错的。

HANDLE hFile = CreateFile( ... );
HANDLE hMap = CreateFileMapping( hFile, ... );
如果CreateFile调用失败,函数返回 INVALID_HANDLE_VALUE,在调用 CreateFileMapping时,系统将创建以页面交换文件为后备存储器的内存映射文件,而不是所希望的以磁盘文件为后备存储器的内存映射文件。而所涉及的内存映射文件创建代码仍然工作正常,所以我们应养成判断函数返回值是否正确的习惯。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
内存映射是一种在不同进程间共享数据的有效方法。通过内存映射,多个exe程序可以将某个共享文件映射到它们各自的内存空间中,并且可以在此文件中存放和读取数据。这样,当一个程序写入数据到共享文件时,其他程序也可以读取这些数据。这就实现了不同exe程序之间的数据交换。 在实际操作中,首先需要创建一个共享文件,并将其映射到内存中。然后,每个程序在自己的地址空间中都可以访问这个映射的内存。对于写操作,程序可以将要写入的数据直接写入映射的内存空间中;对于读操作,程序可以直接从映射的内存空间中读取数据。 通过内存映射实现exe程序间的数据交换具有以下优点: 1. 高效性:内存映射方式下,数据直接从内存中读取,无需磁盘IO操作,因此速度较快。 2. 简单易用:内存映射方式只需要将文件映射到内存,然后进行读写操作即可,无需复杂的通信机制。 3. 数据共享:通过共享文件进行内存映射,不同程序之间可以在同一份数据上进行读写操作,实现数据共享。 然而,内存映射也存在一些限制和注意事项。首先,不同程序访问共享数据时需要进行锁定,以避免并发访问导致的数据错误。其次,共享文件的大小需要注意,过大的文件可能会占用过多的内存。另外,数据交换的顺序和同步也需要细心处理。 总之,通过内存映射可以实现不同exe程序之间的数据交换,提供了一种高效、简单的共享数据的方式。掌握内存映射使用方法和注意事项,可以更有效地实现程序间的数据交换和共享。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值