内核对象和地址空间想必大家都很清楚,在这就不多说了.那么,我们说说内存映像文件~
什么是内存映像文件呢?
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; }