内存映射文件

 

内存映射文件

一、  内存映射文件简介

与虚拟内存一样,内存映射文件也可以用来保留一个地址空间的区域,并将物理存储器提交给该区域,与虚拟内存的差别在于,物理才能出奇来自一个已经位于磁盘上的文件,而不是系统的也文件,一旦该文件被映射,就可以访问它,就如同整个文件已经加载内存一样。

内存映射文件可用于3个不同的目的:

第一:系统使用内存映射文件加载.exedll文件,从而节省了也文件空间和应用程序启动运行所需的时间。

第二:可以使用内存映射文件来访问磁盘上的数据文件。

第三:可以用来同一台计算机上运行的多个进程之间的数据共享。

二、  基于内存映射的创建进程的过程

当线程调用CreateProcess是,系统将执行下列操作步骤

1、系统找出在调用CreateProcess是设定的.exe文件,若找不到则创建失败,返回FALSE

2、系统创建一个新进程内核对象。

3、系统为这新进程创建一个私有地址空间。

4、系统保存一个足够大的地址空间,用于存放.exe文件,该区域需要的位置在.exe文件本身中设定,按照默认设置,.exe文件的基地址是0x00400000

5、当.exe文件被映射奥进程的地址空间之后,系统将访问.exe文件的IAT部分,该部分列出了包含.exe文件中的代码要调用的函数的dll文件,然后系统为每个dll文件调用LoadLibrary函数,若任何一个dll需要更多的dll,那些系统将调用Loadlibrary函数,以便加载这些dll

当调用LoadLibrary函数时,系统将执行系列操作步骤:

1)、系统保留一个足够大的地址空间区域,用于存放该dll,该区域所需要的位置同样在dll文件本身中设定(具体内存参考PE文件结构)。Windows提供的所有标准系统DLL都拥有不同的基地址。

2)、如果系统无法在该DLL的首选基地址上保留一个区域,(已经被另一个DLLEXE占用,或者该区域不够大),此时,系统将寻找另一个地址空间来保留该DLL,并在该DLL中执行重定位操作。

三、使用内存映射文件

1、创建或打开一个文件内核对象

         HANDLE CreateFile(

                   PCSTR pszFileName,                             /*需要创建或打开的文件名称*/

                   DWORD dwDesiredAccess,                   /*读写保护属性*/

                   DWORD dwShareMode,                         /*如何共享*/

                   PSECURITY_ATTRIBUTES psa,                   /*安全性描述符,可设置为NULL*/

                   DWORD dwCreationDisposition,          /*创建方式标识*/

                   DWORD dwFlagsAndAttributes,           /*创建属性标识*/

                   HANDLE hTemplateFile);                     

DWORD dwDesiredAccess可取值

         GENERIC_READ:允许对设备进行读访问

GENERIC_WRITE:允许对设备进行写访问(可组合使用)

0:只允许获取与一个设备有关的信息

DWORD dwShareMode可取值

         0不共享

FILE_SHARE_READ:读共享

FILE_SHARE_WRITE:写共享

DWORD dwCreationDisposition可取值

         CREATE_NEW 创建文件,如文件存在则会出错

CREATE_ALWAYS 创建文件,会改写前一个文件

OPEN_EXISTING 文件必须已经存在。由设备提出要求

OPEN_ALWAYS 如文件不存在则创建它

TRUNCATE_EXISTING 将现有文件缩短为零长度

DWORD dwFlagsAndAttributes可取值

FILE_ATTRIBUTE_ARCHIVE 标记归档属性

   FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或标记为文件在目录中的默认压缩方式

   FILE_ATTRIBUTE_NORMAL 默认属性

   FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录

   FILE_ATTRIBUTE_READONLY 文件为只读

   FILE_ATTRIBUTE_SYSTEM 文件为系统文件

   FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作

   FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作

   FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块

   FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化

   FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化

   FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件

2、创建一个文件映射内核对象

         HANDLE CreateFileMapping(

                   HANDLE hFile,                                       /*想要映射到进程地址空间中的文件句柄*/

                   PSECURITY_ATTRIBUTES pas,                   /*安全性描述符*/

                   DWORD fdwProtect,                              /*读写保护属性*/

                   DWORD dwMaximumSizeHigh,            /*该文件最大字节数的高位*/

                   DWORD dwMaximuxSizeLow,              /*该文件最大字节数的地位*/

                   PCTSTR pszName);                                /*内核对象名称,用于其他进程共享该文件映射对象*/

DWORD fdwProtect的可取值

PAGE_READONLY:以只读方式打开映射

PAGE_READWRITE:以可读、可写方式打开映射

PAGE_WRITECOPY:为写操作留下备份可组合使用下述一个或多个常数

SEC_COMMIT:为文件映射一个小节中的所有页分配内存

SEC_IMAGE:文件是个可执行文件

SEC_RESERVE:为没有分配实际内存的一个小节保留虚拟内存空间

3、将文件数据映射到进程的地址空间

         PVOID MapViewOfFile(

                   HANDLE hFileMappingObject,             /*文件映射内核对象的句柄*/

                   DWORD dwDesiredAccess,                   /*如何访问该数据*/

                   DWORD dwFileOffsetHigh,                            /*需要映射的第一个字节的位置的高位*/

                   DWORD dwFileOffsetLov,                     /*需要映射的第一个字节的位置的低位*/

                   SIZE_T dwNumberOfBytesToMap);     /*需要映射到地址空间的字节数*/

DWORD dwDesiredAccess可取值:

FILE_MAP_WRITE:映射可读可写。文件映射对象必须通过PAGE_READWRITE访问创建

FILE_MAP_READ:映射只读。文件映射对象必须通过PAGE_READPAGE_READWRITE创建

FILE_MAP_ALL_ACCESS FILE_MAP_WRITE相同

FILE_MAP_COPY 映射时保留写操作的副本。文件映射对象必须用PAGE_WRITECOPY创建

4、更新磁盘

         BOOL FlushViewOfFile(

                   PVOID pvAddress,                                 /*需要更新的数据在映射文件中的地址*/

                   SIZE_T dwNumberOfBytesToFlush);    /*需要刷新的字节数*/

5、从进程的地址空间中撤销文件数据的映射

         BOOL UnmapViewOfFile(

PVOID pvBaseAddress);  /*返回区域的基地址,需保持与MapViewOfFile返回值一致*/

6、关闭文件映射对象和文件对象

         CloseHandle(hFileMapping);         /*关闭文件映射对象*/

         CloseHandle(hFile);                        /*关闭文件对象*/

使用内存映射文件:

#include <iostream>

#include <windows.h>

using namespace std;

 

void main()

{

     /*创建硬盘文件,若不存在创建之,若存在打开之*/

     HANDLE file = CreateFile("hello.txt", GENERIC_WRITE|GENERIC_READ,

                                  FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,

                                  FILE_ATTRIBUTE_NORMAL, NULL);

     if(file == INVALID_HANDLE_VALUE)

     {

         cout << "create file false !" << endl;

     }

 

     /*创建文件映射内核对象*/

     HANDLE fileMap = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 512, NULL);

     if(fileMap == NULL)

     {

         cout << "create file mapping false !" << endl;

     }

 

     /*将文件数据映射到进程的地址空间*/

     void * viewFile = MapViewOfFile(fileMap, FILE_MAP_ALL_ACCESS, 0, 0, 512);

     if(viewFile == NULL)

     {

         cout << "view view of file is filse!" << endl;

     }

 

     char * str = "hello world !";

     memcpy(viewFile, str, strlen(str) + 1);

 

     FlushViewOfFile(viewFile, sizeof(int));

 

     CloseHandle(fileMap);

     CloseHandle(file);

     system("pause");

}

使用内存映射文件实现进程间数据共享

#include <iostream>

#include <windows.h>

using namespace std;

 

void main()

{

     /*创建由页文件支持的命名文件映射内核对象*/

     HANDLE fileMap1 = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,

                                               PAGE_READWRITE, 0, 512, "SharedFile1");

     if(fileMap1 == NULL)

     {

         cout << "create file mapping false !" << endl;

     }

 

     /*将文件数据映射到进程的地址空间*/

     void * viewFile1 = MapViewOfFile(fileMap1, FILE_MAP_ALL_ACCESS, 0, 0, 0);

     if(viewFile1 == NULL)

     {

         cout << "view view of file is filse!" << endl;

     }

 

     /*创建由页文件支持的命名文件映射内核对象*/

     HANDLE fileMap2 = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,

                                               PAGE_READWRITE, 0, 512, "SharedFile2");

     if(fileMap1 == NULL)

     {

         cout << "create file mapping false !" << endl;

     }

 

     /*将文件数据映射到进程的地址空间*/

     void * viewFile2 = MapViewOfFile(fileMap2, FILE_MAP_ALL_ACCESS, 0, 0, 0);

     if(viewFile2 == NULL)

     {

         cout << "view view of file is filse!" << endl;

     }

 

     char str1[512];

     char str2[512];

     strcpy(str1, "init string !");

     strcpy(str2, "init string !");

     memcpy(viewFile1, str1, strlen(str1) + 1);

     memcpy(viewFile2, str2, strlen(str1) + 1);

 

     while(true)

     {

         cin >> str1;

         if(!strcmp(str1, "q"))

         {

              break;

         }

         memcpy(viewFile1, str1, strlen(str1) + 1);

         cout << (char *)viewFile2 << endl;

     }

 

     system("pause");

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值