内核对象和地址空间想必大家都很清楚,在这就不多说了.那么,我们说说内存映像文件~

什么是内存映像文件呢?

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;
}