进程间通信--文件映射方式

1. 文件映射(Memory-Mapped Files)  
内存映射文件允许应用程序把文件映射到一个进程的虚拟地址空间,这样文件内的数据就可以用内存读写指令来访问。 
通过内存文件映射,应用程序不必执行文件I/O操作也无需对文件内容进行缓冲处理。内存文件映射的这种特性是非常适合于用来管理大尺寸文件的。

2. 共享内存(Shared Memory)  
Win32 API中共享内存(Shared Memory)实际就是文件映射的一种特殊情况。进程在创建文件映射对象时用INVALID_HANDLE_VALUE来代替文件句柄,就表示了对应的文件映射对象是由操作系统页面文件产生的,其它进程打开该文件映射对象就可以访问该内存块。由于共享内存是用文件映射实现的,所以它也有较好的安全性,也只能运行于同一计算机上的进程之间。

共享内存顾名思义是在内存中创建一个公共区域,供不同的进程间的数据共享。因为是直接对内存进行读写操作,效率非常高,所以共享内存特别适用于大批量的数据传输且实时性要求比较高的场合。

具体操作步骤如下:

1.进程A调用CreateFileMapping创建一个内存映射文件。

2.进程A调用MapViewOfFile获取到映射到文件的内存起始地址,调用memcpy往内存中拷贝数据。

3.进程B调用CreateFileMapping打开进程A创建的内存映射文件。

4.进程B调用MapViewOfFile获取到映射到文件的内存起始地址,调用memcpy从内存中读出数据。

5.通信完后进程A,B分别调用UnmapViewOfFile,CloseHandle取消内存映射和关闭内存映射对象句柄。

参考代码如下:

  1 进程A:
  2 //
  3 //  FUNCTION: ShareMemoryCreate(LPCTSTR szMapName, DWORD dwSize)
  4 //
  5 //  PURPOSE:  create or open a map file
  6 //
  7 //  parameter:
  8 //            szMapName:name of the sharememory
  9 //            dwSize :  size
 10 //  retun   :
 11 //            1:  create a mew file
 12 //            2:  open a file existed
 13 //
 14 //
 15 DWORD ShareMemoryCreate(LPCTSTR szMapName, DWORD dwSize)
 16 {
 17     DWORD dwRet = 1;
 18     HANDLE m_hShareMemory = NULL;
 19
 20     if(NULL == szMapName)
 21         return 0;
 22
 23     if(NULL != m_hShareMemory)
 24         ShareMemoryClose(m_hShareMemory, m_pMapBuffer);
 25     //create the mapfile
 26     m_hShareMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
 27                                    PAGE_READWRITE, 0, dwSize, szMapName);
 28     if(!m_hShareMemory)
 29         return 0;
 30     //the mapfle has existed
 31     if(GetLastError() == ERROR_ALREADY_EXISTS)
 32     {
 33         dwRet = 2;
 34     }
 35     //gain the pointer of sharememory
 36     m_pMapBuffer = MapViewOfFile(m_hShareMemory, FILE_MAP_ALL_ACCESS,
 37                                   0, 0, dwSize);
 38     if(NULL == m_pMapBuffer)
 39     {
 40         CloseHandle(m_hShareMemory);
 41         return 0;
 42     }
 43     //create a mutuex, 用于读写同步
 44     TCHAR szMutexName[MAX_LOADSTRING];
 45     _tcscpy(szMutexName, szMapName);
 46     _tcscat(szMutexName, _T("_Mutex"));
 47     m_hAccessMutex = CreateMutex(NULL, FALSE, szMutexName);
 48     if(NULL == m_hAccessMutex)
 49     {
 50         ShareMemoryClose(m_hShareMemory, m_pMapBuffer);
 51         return 0;
 52     }
 53     return dwRet;
 54 }
 55
 56 //
 57 //  FUNCTION: shareMemoryWrite(void* pBuf,DWORD dwSize,DWORD dwOffset)
 58 //
 59 //  PURPOSE:  write the data into sharememory
 60 //
 61 //  parameter:
 62 //            pbuf:address of the sharememory
 63 //            dwSize :  size of the data
 64 //            dwoffset: offset with the start postion
 65 //  retun   :
 66 //            TRUE
 67 //            FALSE
 68 //
 69 //
 70 BOOL shareMemoryWrite(LPVOID m_pMapBuffer, TCHAR* pBuf,DWORD dwSize,DWORD dwOffset)
 71 {
 72     BOOL bRect;
 73
 74     if(NULL == m_pMapBuffer)
 75         return FALSE;
 76     //收到信号时进行写操作
 77     if(WaitForSingleObject(m_hAccessMutex, INFINITE) == WAIT_OBJECT_0)
 78     {
 79         memcpy((TCHAR *)m_pMapBuffer+dwOffset, pBuf, dwSize);
 80         bRect = TRUE;
 81     }
 82     ReleaseMutex(m_hAccessMutex);
 83     return bRect;
 84
 85 }
 86
 87 //close the sharememory
 88 void ShareMemoryClose(HANDLE m_hShareMemory, LPVOID m_pMapBuffer)
 89 {
 90     if(m_hShareMemory)
 91     {
 92         UnmapViewOfFile(m_pMapBuffer);
 93         CloseHandle(m_hShareMemory);
 94         m_pMapBuffer   = NULL;
 95         m_hShareMemory = NULL;
 96     }
 97     if(m_hAccessMutex)
 98     {
 99         CloseHandle(m_hAccessMutex);
100         m_hAccessMutex = NULL;
101     }
102 }
 进程B //
 2 //  FUNCTION: ShareMemoryCreate(LPCTSTR szMapName, DWORD dwSize)
 3 //
 4 //  PURPOSE:  create or open a map file
 5 //
 6 //  parameter:
 7 //            szMapName:name of the sharememory
 8 //            dwSize :  size
 9 //  retun   :
10 //            1:  create a mew file
11 //            2:  open a file existed
12 //
13 //
14 DWORD ShareMemoryCreate(LPCTSTR szMapName, DWORD dwSize)
15 {
16     DWORD dwRet = 1;
17
18     if(NULL == szMapName)
19         return 0;
20
21     if(NULL != m_hShareMemory)
22         ShareMemoryClose(m_hShareMemory, m_pMapBuffer);
23     //create the mapfile
24     m_hShareMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
25                                    PAGE_READWRITE, 0, SHARE_MEMORY_SIZE, TEXT("sharememoryfile"));
26     if(!m_hShareMemory)
27         return 0;
28     //the mapfle has existed
29     if(GetLastError() == ERROR_ALREADY_EXISTS)
30     {
31         dwRet = 2;
32     }
33     //gain the pointer of sharememory
34     m_pMapBuffer = MapViewOfFile(m_hShareMemory, FILE_MAP_ALL_ACCESS,0, 0, SHARE_MEMORY_SIZE);
35
36     TCHAR szMutexName[MAX_LOADSTRING];
37     _tcscpy(szMutexName, szMapName);
38     _tcscat(szMutexName, _T("_Mutex"));
39     m_hAccessMutex = CreateMutex(NULL, FALSE, szMutexName);
40     if(NULL == m_hAccessMutex)
41     {
42         ShareMemoryClose(m_hShareMemory, m_pMapBuffer);
43         return 0;
44     }
45     return dwRet;
46 }
47 //
48 //  FUNCTION: shareMemoryRead(void* pBuf,DWORD dwSize,DWORD dwOffset = 0)
49 //
50 //  PURPOSE:  read the data from the sharememory
51 //
52 //  parameter:
53 //            pbuf:address of the sharememory
54 //            dwSize :  size of the data
55 //            dwoffset: offset with the start postion
56 //  retun   :
57 //            TRUE
58 //            FALSE
59 //
60 //
61 /**/
62 BOOL shareMemoryRead(LPVOID m_pMapBuffer, TCHAR* pBuf,DWORD dwSize, DWORD dwOffset)
63 {
64     BOOL bRet;
65     if(NULL == m_pMapBuffer)
66         return FALSE;
67     if(WaitForSingleObject(m_hAccessMutex, INFINITE) == WAIT_OBJECT_0)
68     {
69         memcpy(pBuf, (TCHAR *)m_pMapBuffer+dwOffset, dwSize);
70         bRet = TRUE;
71     }
72     ReleaseMutex(m_hAccessMutex);
73
74     return bRet;
75 }
76 //close the sharememory
77 void ShareMemoryClose(HANDLE m_hShareMemory, LPVOID m_pMapBuffer)
78 {
79     if(m_hShareMemory)
80     {
81         UnmapViewOfFile(m_pMapBuffer);
82         CloseHandle(m_hShareMemory);
83         m_pMapBuffer   = NULL;
84         m_hShareMemory = NULL;
85     }
86     if(m_hAccessMutex)
87     {
88         CloseHandle(m_hAccessMutex);
89         m_hAccessMutex = NULL;
90     }
91 }
时间: 2024-10-09 10:22:30

进程间通信--文件映射方式的相关文章

进程间通信——文件

1.信号的局限性 进程虽然高度独立和封闭,但进程依然有通信的需要. 信号--中断,信号能够实现一定程度的进程间通信,但它是高度抽象,所表达的含义是告诉某一个进程什么事情发生了.信号却不能够传递复杂的.有效的.具体的数据,这就是信号的局限性. 就需要其他的手段来构建进程间复杂数据的传递. 2.基于文件的进程间通信 早期的系统中,为了能够让进程之间方便的共享数据,最容易想到的解决方案就是,使用磁盘上的文件系统(因为文件系统对于所有进程都是公开且共享的). 进行文件间通信代码: #include<st

【WIN32进阶之路】:内存映射文件

第一章:源起  遇到一个问题,如果一个客户数据文件有2g大,客户要通过界面查询文件中的数据并用列表控件显示数据,要怎么处理这个文件才能让应用程序不会长时间无响应,客户感觉不到程序的卡顿? 第二章:解决之道 第一反应是用内存映射文件处理大文件,将文件分成数次映射至内存地址空间,避免一次性缓冲整个文件带来的界面长时间无响应,并将暂时不用的内存映射文件取消映射,客户是用列表控件进行显示,那就可以在首次加载的时候只加载第一页的内容就进行显示,之后在缓冲下一页的内容,当用户查看中间页面的内容时可以缓冲将当

centos笔记之文件或目录属性信息

第一版块共11列:第一列:表示文件类型:如:减号'-':普通文件或者可执行命令d:代表目录c:表示字符设备(处理字符的设备,如显示器鼠标)b:块设备(如磁盘.U盘等存文件的)l:软链接文件s:进程间通信文件,只用于本地p:管道文件(用于通信,把某些命令的输出作为其他命令的输入)第2~9列:表示权限 (r可读,w可写,x可执行)2~4三列:表示所属组权限5~7三列:表示所属主权限8~10三列:表示所有者权限第13列:表示高低位,了解即可 第二板块数字列:表示与该文件有具有相同inode 文件或目录

关于前端自动化的一些时间记录

angular的silkydream项目 安装angular的generator npm install -g generator-angular 组建项目 yo angular silkydream 使用git将项目推送至github git add -A git commit -m "finsh" git push origin master 在其他设备拉取项目需要运行 npm install bower install nodejs(yeoman,bower,grunt)介绍 n

saltstack知识点

1 file server configuration salt有一个用ZeroMQ编写的高性能文件服务,它可以用很小的负载快速管理大量的文件.salt的文件服务是一个感知环境(environment aware)的文件服务,什么是环境感知?就是文件可以被分配在多个根目录下,可以在访问时指定文件路径和搜索路径.独特的环境可以跨越多个根目录覆盖,并以灵活的方式来组织文件.  salt默认的文件服务强制使用base环境,这个base环境必须被定义,当没有写明环境定义的时候,就是从这个base环境下载

linux初学之基本命令学习

mkdir 作用:创建目录 语法:mkdir filename 参数:-p 级联创建目录 PS:同一目录下mkdir与touch的文件不可重名,因为在linux下的目录文件和普通文件都视为文件. rmdir 作用:删除目录 语法:rmdir filename 参数:-p 级联删除目录 rm 作用:删除文件 语法:rm filename 参数: -r 删除目录 参数:-f 强制删除,不显示删除询问 PS:rm -rf a/b/c 与 rmdir -p a/b/c 效果上相同. cp 作用:复制文件

Windows API 学习指南

1.WindowsAPI开发入门2.Windows数据类型3.Windows数据类型与WindowsAPI函数4.Windows数据结构5.将系统目录信息写入文件6.窗口创建以及消息处理7.使用对话框资源创建窗口8.使用MFC创建对话框窗口9.宽字符10.三种版本11.字符转换12.遍历卷13.驱动器属性14.磁盘容量15.文件操作的四种方法16.文件操作(一)17.文件操作(二)18.目录操作(一)19.目录操作(二)20.目录操作(三)21.文件属性和时间22.内存映射文件23.系统信息(一

分布式技术一周技术动态 2016.08.07

searcher 分布式纵向方向主要涵盖的范围包括分布式系统理论和设计实践, 资源管理和虚拟化技术, 大规模服务稳定性技术, DevOps和自动运维技术等方面, “分布式方向一周技术动态"是我每周总结和整理的关于分布式方向的精选技术文章, 希望以此让大家能够跟踪业界相关的技术动态, 培养大家对分布式系统的兴趣, 学习分布式系统理论和设计思路, 辅助大家的日常工作. 每周的技术动态会在hi群和邮件组里同步发布, 欢迎大家阅读. 对于后续 分布式技术动态 有任何意见或者建议, 大家可以随时联系我.

MyBatis入门学习(三)

在实际开发中,我们希望文件配置是分类配置存放,需要的时候引入即可.如果多文件的配置混合配置使用,那么对项目的后期维护将增加难度. 一.对于连接数据库的配置单独放在一个properties文件中 1.对于之前的配置我们是将数据库配置放置在conf.xml文件中,如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//