FileMapping

        FileMapping       

 

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

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

系统使用内存映射文件,以便加载和执行. e x eD L L文件。这可以大大节省页文件空间和应用程序启动运行所需的时间。

可以使用内存映射文件来访问磁盘上的数据文件。这使你可以不必对文件执行I / O操作,并且可以不必对文件内容进行缓存。

可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据。Wi n d o w s确实提供了其他一些方法,以便在进程之间进行数据通信,但是这些方法都是使用内存映射文件来实现的,这使得内存映射文件成为单个计算机上的多个进程互相进行通信的最有效的方法。

一.内存映射文件的函数包括

CreateFileMapping , OpenFileMapping, MapViewOfFile, UnmapViewOfFile FlushViewOfFile

用法如下:

1HANDLE CreateFileMapping(

HANDLE                  hFile,              // 一个文件句柄

LPSECURITY_ATTRIBUTE  lpAttributes,         // 定义内存映射文件对象是否可以被承

DWORD                   flProtect,           // 该内存映射文件的保护类型

DWORD                   dwMaximumSizeHigh,// 内存映射文件的长度

DWORD                   dwMaximumSizeLow, //

LPCTSTR                  lpName             // 内存映射文件的名字

)

hFile       指定要映射的文件的句柄,如果这是一个已经打开的文件的句柄(CreateFile函数的返回值),那么将建立这个文件的内存映射文件,如果这个参数为-1,则建立共享内存。

lpAttribute  安全属性,一般设为NULL

flProtect    指定映射文件的保护类型,它的取值可以是PAGE_READONLY(内存页面只读) PAGE_READWRITE(内存页面可读写)。

dwMaximumSizeHigh dwMaximumSizeLow参数组合指定了一个64位的内存映射文件的长度。一种简单的方法是将这两个参数全部设置为0,那么内存映射文件的大小将与磁盘文件大小一致。

2HANDLE OpenFileMapping(

DWORD               dwDesiredAccess,    // 指定保护类型

BOOL                  bIsInheritHandle,     // 返回的句柄是否可以被继承

LPCSTR                lpName             // 创建对象时使用的名字

如果创建的是共享内存,其他进程不能再使用CreateFileMapping函数去创建同名的内存映射文件对象,而要使用OpenFileMapping函数打开已创建好的对象。

dwDesiredAcess   指定保护类型有FILE_MAP_WRITEFILE_MAP_READ

3LPVOID MapViewOfFile(

HANDLE  hFileMappingObject,    // 前两个函数返回的内存映射文件的句柄

DWORD  dwDesiredAcess,      // 保护类型FILE_MAP_READ ,FILE_MAP_WRITE

DWORD  dwFileOffsetHight,     // 从文件的那个地址开始映射

DWORD  dwFileOffsetLow,

SIZE_T   dwNumberOfBytesToMap // 要映射的字节数,为0则映射整个文件

4BOOL UnmapViewOfFile( LPCVOID  lpBaseAddress )

当不再使用内存映射文件时,可以通过UmmapViewOfFile函数撤销映射并使用CloseHandle函数关闭内存映射文件的句柄。

5BOOL FlushViewOfFile(

LPCVOID   lpBaseAddress,  // 开始的地址

SIZE_T     dwNumberOfBytesToFlush // 数据块的大小

如果修改了映射视图中的内存,系统会在试图撤销映射或文件映射对象被删除时自动将数据写到磁盘上,但程序也可以根据需要将视图中的数据立即写到磁盘上。

二.使用步骤

1.  使用CreateFileMapping创建一个内存映射文件内核对象,告诉操作系统内存映射文件需要的物理内存大小,这个步骤决定了内存映射文件的用途――究竟是为磁盘上的文件建立内存映射还是为多个进程共享数据建立共享内存。或者使用OpenFileMapping打开映射文件内核对象。

2.  映射文件映射对象的全部或一部分到进程的地址空间,可以认为该操作是为文件中的内容分配线型地址空间,并将线型地址和文件内容对应起来,完成该操作的函数是MapViewOfFile

三.使用内存映射文件读文件的具体过程可以这样:

(1)        调用CreateFile函数打开想要映射的文件,得到文件句柄hFile

(2)        调用CreateFileMapping函数,并传入文件句柄hFile,为该文件创建一个内存映射内核对象,得到内存映射文件的句柄hMap

(3)        调用MapViewOfFile函数映射整个文件或一部分到进程的虚拟地址空间。该函数返回文件映射到内存后的起始地址。使用指向这个地址的指针就可以读取文件的内容了。

(4)        调用UnmapViewOfFile函数来解除文件映射。

(5)        调用CloseHandle函数关闭文件对象,必须传入内存映射文件句柄hMap

(6)        调用CloseHandle函数关闭文件对象,必须传入文件句柄hFile

四.进程间共享内存:

共享内存主要是通过映射机制实现的。Windows下进程的地址空间是相互隔离的,但在物理上却是重叠的。所谓的重叠是指同一块内存区域可能被多个进程同时使用。当调用CreateFileMapping创建命名的内存映射文件对象时,Windows即在物理内存中申请了一块指定大小的内存区域,返回文件映射对象的新句柄hMap。为了能够访问这块区域必须调MapViewOfiFile函数,促使Windows将此内存空间映射到进程的地址空间中。当在其他进程中访问这块区域时,则必须使用OpenFileMapping函数来取得对象句柄hMap,并调用MapViewOfFile函数得到此内存空间的一个映射。这样一来,系统就把同一块内存区域映射到了不同进程的地址空间中,从而达到共享内存的目的。

示例:

#define  BUF_SIZE 256
#define  FILE_MAP_NAME  "Global//{42561571-5A43-4c5c-9D76-4132D70A8968}"

The first process:

HANDLE  hFile = CreateFile("c://mapping.txt",

  GENERIC_READ|GENERIC_WRITE,

  FILE_SHARE_READ|FILE_SHARE_WRITE,

  NULL,

  OPEN_EXISTING,

  FILE_ATTRIBUTE_NORMAL,

  NULL);
if ( !hFile )
{
  return;
}



HANDLE hMapFile = NULL;

hMapFile = CreateFileMapping( hFile,
  NULL ,
  PAGE_READWRITE,
  0, /*一定为0 否则磁盘空间不足*/
  BUF_SIZE, /*不能为0*/
  FILE_MAP_NAME /*Global/" or "Local/" 其他都不能带有/ */
  );

//hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,/*(HANDLE)0xFFFFFFFF*/
// //NULL,
// ShareRestrictedSD.GetSA(),
// PAGE_READWRITE,
// 0,
// BUF_SIZE,
// FILE_MAP_NAME
// );
if ( hMapFile == NULL )
{
  DWORD dwErr = GetLastError();
  return;
}

void* pMapBuf = NULL;
if ( ( pMapBuf = MapViewOfFile(hMapFile,
  FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE)) == NULL)
{
  DWORD dwErr = GetLastError();
  return;
}
memset(pMapBuf, 0, 100);
strcpy( (char *)pMapBuf, "create file text" );

UnmapViewOfFile( pMapBuf );
//CloseHandle( hMapFile );
CloseHandle( hFile );

The Second Process:

HANDLE hMapFile = NULL;
if ( (hMapFile = OpenFileMapping(
  FILE_MAP_ALL_ACCESS,
  FALSE,
  //NULL,
  FILE_MAP_NAME
  )) == NULL)
{
  DWORD dwErr = GetLastError();
  return;
}

void* pMapBuf = NULL;
if ( ( pMapBuf = MapViewOfFile(hMapFile,
  FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE)) == NULL)
{
  DWORD dwErr = GetLastError();
  return;
}

strcpy( (char*)pMapBuf, "open file text");

UnmapViewOfFile( pMapBuf );
CloseHandle( hMapFile );

 

转:http://blog.csdn.net/ljfxmf/article/details/3341226

好的,您想了解如何从Filemapping中读取数据并使用CreateFile函数写入文件。首先,需要使用CreateFileMapping函数创建一个文件映射对象,将文件映射到进程的地址空间中。然后使用MapViewOfFile函数将文件映射到进程的地址空间中并返回指向该区域的指针。接下来,您可以使用指针访问文件映射中的数据。最后,使用CreateFile函数创建一个新文件或打开已存在的文件,并使用WriteFile函数将数据写入该文件。 以下是一个简单的示例代码,展示如何实现从Filemapping中读取数据并使用CreateFile函数写入文件: ``` HANDLE hFile = CreateFile("output.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("Error creating file. Error code: %d\n", GetLastError()); return; } HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, "MyFileMap"); if (hMapFile == NULL) { printf("Error creating file mapping. Error code: %d\n", GetLastError()); CloseHandle(hFile); return; } LPVOID lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 1024); if (lpMapAddress == NULL) { printf("Error mapping view of file. Error code: %d\n", GetLastError()); CloseHandle(hMapFile); CloseHandle(hFile); return; } DWORD dwBytesWritten; if (!WriteFile(hFile, lpMapAddress, 1024, &dwBytesWritten, NULL)) { printf("Error writing file. Error code: %d\n", GetLastError()); } UnmapViewOfFile(lpMapAddress); CloseHandle(hMapFile); CloseHandle(hFile); ``` 注意:此示例代码仅供参考,您需要根据自己的需求进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值