windows文件映射

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;

}

源代码:

 1 // Server.cpp : 定义控制台应用程序的入口点。
 2 //
 3
 4 #include "stdafx.h"
 5 #include <windows.h>
 6
 7 int main()
 8 {
 9
10     HANDLE MappingHandle = NULL;
11     PVOID  BaseAddress = NULL;
12     //创建一个物理文件无关的内存映射
13     //创建了一个和物理文件大小无关的内存空间
14     MappingHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,0x1000, L"刘大大别是妖怪吧");
15
16     if (MappingHandle==NULL)
17     {
18         return 0;
19     }
20
21     BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
22
23
24     __try
25     {
26         memcpy(BaseAddress, "HelloClient", strlen("HelloClient")+1);
27
28         printf("Input AnyKey To Continue\r\n");
29         getchar();
30
31         printf("%s\r\n", BaseAddress);
32     }
33     __except (EXCEPTION_EXECUTE_HANDLER)
34     {
35         printf("异常\r\n");
36         goto Exit;
37     }
38
39
40
41
42 Exit:
43     if (MappingHandle!=NULL)
44     {
45         CloseHandle(MappingHandle);
46         MappingHandle = NULL;
47     }
48
49     printf("Input AnyKey To Exit\r\n");
50     getchar();
51     return 0;
52 }

Server.cpp

 1 // Client.cpp : 定义控制台应用程序的入口点。
 2 //
 3
 4 #include "stdafx.h"
 5 #include <windows.h>
 6
 7 int main()
 8 {
 9     HANDLE MappingHandle = NULL;
10     PVOID  BaseAddress = NULL;
11
12     MappingHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,L"刘大大别是妖怪吧");
13
14     if (MappingHandle==NULL)
15     {
16         return 0;
17     }
18     BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
19     __try
20     {
21         printf("%s\r\n", BaseAddress);
22         memcpy(BaseAddress, "HelloServer", strlen("HelloServer") + 1);
23
24     }
25     __except (EXCEPTION_EXECUTE_HANDLER)
26     {
27         printf("异常\r\n");
28         goto Exit;
29     }
30
31 Exit:
32
33     if (MappingHandle!=NULL)
34     {
35         CloseHandle(MappingHandle);
36         MappingHandle = NULL;
37     }
38     printf("Input AnyKey To Exit\r\n");
39     getchar();
40     return 0;
41 }

时间: 2024-10-20 15:49:37

windows文件映射的相关文章

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

#include <windows.h>#include <string.h>#include <string>#include <iostream>using namespace std; int main(int argc, char *argv[]){ // 步骤1 打开文件FILE_FLAG_WRITE_THROUGH HANDLE hFile = CreateFile( "demo.txt", GENERIC_WRITE | G

windows 文件内存映射

static int MapLogFile(void) { hFile = CreateFile(".\\db.bin", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL); if (INVALID_HANDLE_VALUE == hFile) { goto err; } hMap = CreateFileMapping(h

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

本文通过创建文件内存映射类,学习windows内存映射相关知识:创建内存映射文件后,可以按照内存操作方式操作文件 感谢http://blog.csdn.net/csafu/article/details/8602142, 引用部分内容"文件映射问题 内存映射文件并不是简单的文件I/O操作,实际用到了Windows的核心编程技术--内存管理. 所以,如果想对内存映射文件有更深刻的认识,必须对Windows操作系统的内存管理机制有清楚的认识, 内存管理的相关知识非常复杂,超出了本文的讨论范畴,在此就

Ubuntu和Windows文件Samba共享

1.在Ubuntu下配置Samba共享文件夹/work和/work1 1.1.安装samba sudo apt-get install samba 1.2.配置samba vim /etc/samba/smb.conf 在文件末尾添加下面代码: #用户samba可以访问 [work] comment = ubuntu-Larack-10.13.14.122:/work path = /work writeable = yes public = no valid users = samba #所有

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

CentOS虚拟机如何设置共享文件夹,并在Windows下映射网络驱动器? 转自这里 一.为什么要这么做? 最近在做Linux下的软件开发,但又想使用Windows下的编程工具“Source Insight”. 二.安装环境 本机系统:Windows 7 旗舰版 VMware:VMware Workstation 9.0 CentOS:CentOS 6.4 网络适配器设置为:NAT 转换 三.查看是否已经安装“samba” 命令:rpm -qa|grep samba 输出结果: samba-cl

67.文件映射为内存进行操作与多线程 以及 文件映射到内存根据索引进行内存来实现读取多线程操作

问题引出: //有限的额内存情况怎么干活//索引载入内存,多线程//索引映射为内存 一.载入内存,按行读取进行多线程 定义路径以及其他信息 1 char path[256] = "kaifangX.txt"; 2 char indexpath[256] = "indexkf.txt"; 3 #define N 20151574 创建索引 1 struct index 2 { 3 int *pindex;//地址 4 int length; 5 }allindex =

Windows文件传输篇:怎么上传文件到服务器?

很多时候,我们需要把文件传输到服务器上进行运行.部署等操作,在使用windows服务器的时候,我们都会遇到这样的问题:我们应该怎么上传文件到服务器?有没有简单的方法来实现本地文件上传到服务器呢? Windows文件传输方法之一: 将需上传的文件打包压缩,利用邮箱附件功能发到另一邮箱,随后在服务器上登录邮箱下载. Windows文件传输方法之二: 将数据上传至百度网盘或者微云等第三方存储服务,在服务器上登录即可下载. Windows文件传输方法之三: 远程登录服务器时,通过本地磁盘映射功能,将本地

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

一.为什么要这么做? 最近在做Linux下的软件开发,但又想使用Windows下的编程工具“Source Insight”. 二.安装环境 本机系统:Windows 7 旗舰版 VMware:VMware Workstation 9.0 CentOS:CentOS 6.4 网络适配器设置为:NAT 转换 三.查看是否已经安装“samba” 命令:rpm -qa|grep samba 输出结果: samba-client-3.0.33-3.28-1.el5samba-common-3.0.33-3

【超实用】图解--如何使用本地的dtd文件映射

以前一直很苦恼,如果电脑上不了网,就比较麻烦了,自己在配置HIbernate的属性的时候,不知道属性名有没有写错.. 现在和大家分享一下,毕竟自己痛苦过了,大家不要和我一样痛苦. [超实用]图解--如何使用本地的dtd文件映射,布布扣,bubuko.com