0x01 使用文件映射实现共享内存。

  用内存映射文件实现进程间的通讯:Windows中的内存映射文件的机制为我们高效地操作文件提供了一种途径,它允许我们在进程中保留一段内存区域,把硬盘或页文件上的目标文件映射到这段虚拟内存中。注意:在程序实现中必须考虑各进程之间的同步问题。

  FileMapping用于将存在于磁盘的文件放进一个进程的虚拟地址空间,并在该进程的虚拟地址空间中产生一个区域用于“存放”该文件,这个空间就叫做File View(存放在进程的虚拟内存中),系统并同时产生一个File Mapping Object(存放于物理内存中)用于维持这种映射关系,这样当多个进程需要读写那个文件的数据时,它们的File View其实对应的都是同一个File Mapping Object,这样做可节省内存和保持数据的同步性,并达到数据共享的目的。

0x02  细节

1)物理文件句柄

  任何可以获得的物理文件句柄,如果需要创建一个物理文件无关的内存映射也无妨,将它设置成为 0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了.

  如果需要和物理文件关联,要确保你的物理文件创建的时候的访问模式和"保护设置"匹配,比如:物理文件只读,内存映射需要读写就会发生错误。推荐你的物理文件使用独占方式创建。

  如果使用 INVALID_HANDLE_VALUE,也需要设置需要申请的内存空间的大小,无论物理文件句柄参数是否有效,这样 CreateFileMapping就可以创建一个和物理文件大小无关的内存空间,甚至超过实际文件大小,如果物理文件有效,而大小参数为0,则返回给你的是一个和物理文件大小一样的内存空间地址范围。返回给你的文件映射地址空间是可以通过复制,集成或者命名得到,初始内容为0。

2)保护设置

  就是安全设置,不过一般设置NULL就可以了,使用默认的安全配置. 在win2k下如果需要进行限制,这是针对那些将内存文件映射共享给整个网络上面的应用进程使用是,可以考虑进行限制.

3)高位文件大小

  32位地址空间,设置为0。

4) 共享内存名称

  命名可以包含 "Global"或者 "Local" 前缀在全局或者会话名空间初级文件映射.其他部分可以包含任何除了()以外的字符,可以参考 Kernel Object Name Spaces.

5)调用CreateFileMapping的时候GetLastError的对应错误

  ERROR_FILE_INVALID 如果企图创建一个零长度的文件映射,应有此报
  ERROR_INVALID_HANDLE 如果发现你的命名内存空间和现有的内存映射,互斥量,信号量,临界区同名就麻烦了
  ERROR_ALREADY_EXISTS 表示内存空间命名已经存在

  使用函数CreateFileMapping创建一个想共享的文件数据句柄,然后使用MapViewOfFile来获取共享的内存地址,然后使用OpenFileMapping函数在另一个进程里打开共享文件的名称,这样就可以实现不同的进程共享数据。

  

0x03  API

  1.内存映射API函数CreateFileMapping创建一个有名字标识的共享内存

  

WINBASEAPI
_Ret_maybenull_
HANDLE
WINAPI
CreateFileMappingW(
_In_ HANDLE hFile, // 映射文件的句柄,若设为0xFFFFFFFF(即:INVALID_HANDLE_VALUE)则创建一个进程间共享的对象,(即创建了一个和物理文件大小无关的内存空间)
_In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, //安全属性
_In_ DWORD flProtect, //保护方式
_In_ DWORD dwMaximumSizeHigh, //对象的大小
_In_ DWORD dwMaximumSizeLow,
_In_opt_ LPCWSTR lpName //映射文件名,即共享内存的名称
);

  与虚拟内存类似,保护方式参数可以是PAGE_READONLY或是PAGE_READWRITE。如果多进程都对同一共享内存进行写访问,则必须保持相互间同步。映射文件还可以指定PAGE_WRITECOPY标志,可以保证其原始数据不会遭到破坏,同时允许其他进程在必要时自由的操作数据的拷贝。

MappingHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,L"刘大大别是妖怪吧");

  

  2.在创建文件映射对象后,服务器端进程调用MapViewOfFile函数映射到本进程的地址空间内

BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

  

 

  3、客户端进程访问共享内存对象,需要通过内存对象名调用OpenFileMapping函数,以获得共享内存对象的句柄

MappingHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,L"刘大大别是妖怪吧");

  

  4、如果客户端进程获得共享内存对象的句柄成功,则调用MapViewOfFile函数来映射对象视图。用户可以使用该对象视图来进行数据读写操作,以达到数据通讯的目的。

例:映射缓存区视图

BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

  

  5、当用户进程结束使用共享内存后,调用UnmapViewOfFile函数以取消其地址空间内的视图:

if (BaseAddress)

{

  UnmapViewOfFile(BaseAddress);

  SharedMapView=NULL;

}

源代码:

 // Server.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <windows.h> int main()
{ HANDLE MappingHandle = NULL;
PVOID BaseAddress = NULL;
//创建一个物理文件无关的内存映射
//创建了一个和物理文件大小无关的内存空间
MappingHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, ,0x1000, L"刘大大别是妖怪吧"); if (MappingHandle==NULL)
{
return ;
} BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, , , ); __try
{
memcpy(BaseAddress, "HelloClient", strlen("HelloClient")+); printf("Input AnyKey To Continue\r\n");
getchar(); printf("%s\r\n", BaseAddress);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("异常\r\n");
goto Exit;
} Exit:
if (MappingHandle!=NULL)
{
CloseHandle(MappingHandle);
MappingHandle = NULL;
} printf("Input AnyKey To Exit\r\n");
getchar();
return ;
}

Server.cpp

 // Client.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <windows.h> int main()
{
HANDLE MappingHandle = NULL;
PVOID BaseAddress = NULL; MappingHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,L"刘大大别是妖怪吧"); if (MappingHandle==NULL)
{
return ;
}
BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, , , );
__try
{
printf("%s\r\n", BaseAddress);
memcpy(BaseAddress, "HelloServer", strlen("HelloServer") + ); }
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("异常\r\n");
goto Exit;
} Exit: if (MappingHandle!=NULL)
{
CloseHandle(MappingHandle);
MappingHandle = NULL;
}
printf("Input AnyKey To Exit\r\n");
getchar();
return ;
}

windows文件映射的更多相关文章

  1. 一个简单但详细的解释Windows文件映射读取数据文件的例子

    #include <windows.h>#include <string.h>#include <string>#include <iostream>u ...

  2. windows内存映射文件

    http://shushanyegui.duapp.com/?p=731 在描述内存映射文件之前 我们先来写一个系统通过I/O来读写磁盘文件的小程序 #include "stdafx.h&q ...

  3. 文件映射(Windows核心编程)

    映射内存的可执行文件和dll 当一个线程调用CreateProcess的时候,系统会执行以下步骤: 系统会先确定CreateProcess所指定的可执行文件的所在位置.如果找不到文件,那么Create ...

  4. windows内存映射学习及帮助类实现

    本文通过创建文件内存映射类,学习windows内存映射相关知识:创建内存映射文件后,可以按照内存操作方式操作文件:支持32位程序处理超过4G大小的文件. 感谢http://blog.csdn.net/ ...

  5. Windows文件操作的API函数[转载]

    在VC中,大多数情况对文件的操作都使用系统提供的 API 函数,但有的函数我们不是很熟悉,以下提供一些文件操作 API 函数介绍: 一般文件操作 API CreateFile 打开文件 要对文件进行读 ...

  6. (代码篇)从基础文件IO说起虚拟内存,内存文件映射,零拷贝

    上一篇讲解了基础文件IO的理论发展,这里结合java看看各项理论的具体实现. 传统IO-intsmaze 传统文件IO操作的基础代码如下: FileInputStream in = new FileI ...

  7. CentOS虚拟机如何设置共享文件夹,并在Windows下映射网络驱动器?

    一.为什么要这么做? 最近在做Linux下的软件开发,但又想使用Windows下的编程工具“Source Insight”. 亲测有效.  要注意查看smb.conf.example,centos7的 ...

  8. [转]CentOS虚拟机如何设置共享文件夹,并在Windows下映射网络驱动器?

    CentOS虚拟机如何设置共享文件夹,并在Windows下映射网络驱动器? 转自这里 一.为什么要这么做? 最近在做Linux下的软件开发,但又想使用Windows下的编程工具“Source Insi ...

  9. Ubuntu和Windows文件Samba共享

    1.在Ubuntu下配置Samba共享文件夹/work和/work1 1.1.安装samba sudo apt-get install samba

随机推荐

  1. English trip V1 - B 3. I'd Like a Room,Please 请给我一间房? Teacher:Julia Key:

    In this lesson you will learn to say what you need. 课上内容(Lesson) twin size bed  单人床 elevator     n. ...

  2. 20170907wdVBA_ImportPicturesBaseOnExcel

    Public Sub ImportPicturesBaseOnExcel() Dim shp As Object Dim xlApp As Object Dim Wb As Object Dim Rn ...

  3. vue组件,axios ,路由

    组件(Component)自定义封装的功能. 把一个功能相关的[HTML.css和javascript]代码封装在一起组成一个整体的代码块封装模式,我们称之为“组件”. 组件就是一个html网页中的功 ...

  4. 前端Vue之vue的基本操作

    1.1 vue.js的快速入门使用 vue.js是目前前端web开发最流行的工具库之一,由尤雨溪在2014年2月发布的. 另外几个常见的工具库:react.js /angular.js 官方网站: 中 ...

  5. 廖雪峰网站:学习python基础知识—list和tuple(二)

    1.list """ Python内置的一种数据类型是列表:list. list是一种有序的集合,可以随时添加和删除其中的元素. """ c ...

  6. 『TensorFlow』高级高维切片gather_nd

    gather用于高级切片,有关官方文档的介绍,关于维度的说明很是费解,示例也不太直观,这里给出我的解读,示例见下面,     indices = [[0, 0], [1, 1]]    params ...

  7. apache2反向代理

    1.安装 Apache2 sudo apt-get install apache2 2.重启服务器 sudo /etc/init.d/apache2 restart 3.虚拟主机配置 启用这几个模块 ...

  8. [python] 查找列表中重复的元素

    a = [1, 2, 3, 2, 1, 5, 6, 5, 5, 5] b = set(a) for each_b in b: count = 0 for each_a in a: if each_b ...

  9. list排序,顺序,倒序

    Collections.sort(list); // 顺序排列 Collections.reverse(list); // 倒序排列 Collections.shuffle(list); // 无序

  10. SpringMVC,Controller的返回页面类型以及路径设置默认值

    一般设置在spring-servlet.xml里面设置 <!-- 对转向页面的路径解析.prefix:前缀, suffix:后缀 --> <bean class="org. ...