内核对象和地址空间想必大家都很清楚,在这就不多说了.那么,我们说说内存映像文件~
什么是内存映像文件呢?
Windows会给每个进程分配4GB地址空间0x00000000~0xFFFFFFFF(32系统)这个空间仅仅是内存地址的范围,而不是计算机的物理存储RAM空间,因而又称为虚拟内存空间。
它经过保留,提交到物理存储器。如果映射的物理存储器是系统分页文件那么,这叫虚拟内存,如果映射的物理存储器是普通文件,这叫内存映像文件。
在必要读写访问时,系统才会写到RAM中或从RAM中写回来。
内存映像文件的应用:
1. 系统使用内存映像文件载入和执行.EXE和.DLL文件。一方面节省了系统分页文件空间,另一方面缩短了加载应用程序开始执行所需的时间。
2. 使用内存映像文件访问磁盘上的数据文件。绕开对文件实行I/O操作和对文件内容的缓冲,交由操作系统内核去完成。
3. 使用内存映像文件可以实现在多个进程间彼此共享数据。Windows提供了在进程间进行数据通信的其它多种方法。但这些方法也是通过内存映像文件来实现的,所以内存映像文件是实现进程间通信最有效率的方法。
内存映像文件的使用参考下面示例(MMFileDemo)
// MMFileDemo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <WINDOWS.H>
DWORD MMFileWrite()
{
//1>创建文件内核对象
HANDLE hFile = ::CreateFile(
"MMData.dat", //文件名
GENERIC_WRITE|GENERIC_READ, //可以将数据写入文件
0, //不共享数据
NULL, //默认安全属性
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
return 0x01;//失败
}
//2>创文件映射内核对象
HANDLE hMap = ::CreateFileMapping(
hFile, //CreateFile创建的内核对象
NULL, //默认安全属性
PAGE_READWRITE, //当文件映射对象被映射时,可以读取和写入文件的数据
0, //文件最大size的高位
100, //文件最大size的低位
NULL //NULL匿名对象
);
if (hMap == NULL)
{
::CloseHandle(hFile);
return 0x02;//失败
}
//3>将文件数据映射到进程的地址空间
PVOID pFile = ::MapViewOfFile(
hMap, //CreateFileMapping创建的内核对象
FILE_MAP_ALL_ACCESS, //可以读取和写入文件数据
0,
0,
0);
if (pFile == NULL)
{
::CloseHandle(hMap);
::CloseHandle(hFile);
return 0x03;//失败
}
//4>向映射文件中写入数据(数据在缓冲区中)
PBYTE pbFile = (PBYTE)pFile;
pbFile[0] = 0x65;//0x65 = 'e'
//卸载Map时,提交缓冲区中数据到文件中
::UnmapViewOfFile(pbFile);
::CloseHandle(hMap);
::CloseHandle(hFile);
return 0x00;
}
DWORD MMFileRead()
{
//1>创建文件内核对象
HANDLE hFile = ::CreateFile(
"MMData.dat", //文件名
GENERIC_READ, //可以将数据读入文件
0, //不共享数据
NULL, //默认安全属性
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
return 0x01;//失败
}
//2>创文件映射内核对象
HANDLE hMap = ::CreateFileMapping(
hFile, //CreateFile创建的内核对象
NULL, //默认安全属性
PAGE_READONLY, //当文件映射对象被映射时,可以读取文件的数据
0, //文件最大size的高位
100, //文件最大size的低位
NULL //NULL匿名对象
);
if (hMap == NULL)
{
::CloseHandle(hFile);
return 0x02;//失败
}
//3>将文件数据映射到进程的地址空间
PVOID pFile = ::MapViewOfFile(
hMap, //CreateFileMapping创建的内核对象
FILE_MAP_READ, //可以读取和写入文件数据
0,
0,
0);
if (pFile == NULL)
{
::CloseHandle(hMap);
::CloseHandle(hFile);
return 0x03;//失败
}
//4>向映射文件中写入数据(数据在缓冲区中)
PBYTE pbFile = (PBYTE)pFile;
printf("%c\n", pbFile[0]);
//卸载Map
::UnmapViewOfFile(pbFile);
::CloseHandle(hMap);
::CloseHandle(hFile);
return 0x00;
}
int main(int argc, char* argv[])
{
DWORD dwRet = 0x00;
if(dwRet = MMFileWrite() != 0)
{
printf("MMFileWrite()函数调用失败[0x%02x]。\n", dwRet);
return dwRet;
}
if(dwRet = MMFileRead() != 0)
{
printf("MMFileRead()函数调用失败[0x%02x]。\n", dwRet);
}
return dwRet;
}