曲径通幽论坛

标题: MapViewOfFile() -- 将文件视图映射到调用进程空间 [打印本页]

作者: beyes    时间: 2012-2-20 15:16
标题: MapViewOfFile() -- 将文件视图映射到调用进程空间
MapViewOfFile() 原型如下:
[C++] 纯文本查看 复制代码
LPVOID WINAPI MapViewOfFile(
  __in  HANDLE hFileMappingObject,
  __in  DWORD dwDesiredAccess,
  __in  DWORD dwFileOffsetHigh,
  __in  DWORD dwFileOffsetLow,
  __in  SIZE_T dwNumberOfBytesToMap
);

该函数将文件视图映射到调用进程空间。在调用该函数之前,我们会调用 CreateFileMapping()  创建一个映射对象,对象相应的文件的内容会被映射到物理内存中,但如果我们接下来要对这些内容进行读取写入,那么需要使用 MapViewOfFile() 函数将这些内容的一部分或全部(文件视图)映射到调用进程的虚拟地址空间中。

第 1 个参数 hFileMappingObject 一般是由 CreateFileMapping() 或 OpenFileMapping() 所返回的映射对象的句柄。

第 2 个参数 dwDesiredAccess 是操作类型,可以是 FILE_MAP_ALL_ACCESS,FILE_MAP_COPY,FILE_MAP_READ 和 FILE_MAP_WRITE 中的一种。

第 3 个参数 dwFileOffsetHigh 是映射文件偏移的高 32 位。

第 4 个参数 dwFileOffsetLow 是映射文件偏移的低 32 位。

第 5 个参数 dwNumberOfBytesToMap 是映射到文件视图(view)的字节数。

文件映射与文件视图(View)机理如下图所示:


测试代码
[C++] 纯文本查看 复制代码
#include "stdafx.h"

#define FILE_MAP_START 0x28804    //文件映射起始位置
#define BUFSIZE    1024            // 内存大小

int _tmain(int argc, _TCHAR* argv[])
{
    setlocale (LC_ALL, "CHS");

    HANDLE    hMapFile;    // 文件内存映射区域的句柄
    HANDLE  hFile;        // 文件的句柄
    
    DWORD    dBtyesWritten;    // 写入的字节数
    DWORD    dwFileSize;        // 文件大小
    DWORD    dwFileMapSize;    // 文件映射的大小
    DWORD    dwMapViewSize;    // 视图(View)大小
    DWORD    dwFileMapStart;    // 文件映射视图起始位置
    DWORD    dwSysGran;        // 系统内存分配粒度
    
    SYSTEM_INFO    SysInfo;    // 系统信息
    LPVOID    lpMapAddress;    // 内存映射区域起始位置
    PCHAR    pData;            // 数据

    INT    i;                    // 循环变量
    INT iData;
    INT iViewDelta;            

    BYTE    cMapBuffer[32];    // 存储从 mapping 中读出的数据

    //创建一个文件
    hFile = CreateFile (argv[1], GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    
    if (hFile == INVALID_HANDLE_VALUE) {
        printf ("Create file error\n");
        return (-1);
    }

    //依次写入整数,一共 65535 个,共 65535*4 个字节
    for (i = 0; i < 65535; i++)
        WriteFile (hFile, &i, sizeof(i), &dBtyesWritten, NULL);
    
    //检查写入后文件的大小
    dwFileSize = GetFileSize (hFile, NULL);
    _tprintf (TEXT("文件大小:%d\n"), dwFileSize);

    /* 获取系统信息,内存分配粒度(64K)
     * 下面几个计算是为了映射的数据与系统内存分配粒度对其,提高内存访问效率
     */
    GetSystemInfo (&SysInfo);

    dwSysGran = SysInfo.dwAllocationGranularity;    //内存分配粒度,一般为 64KB

    //计算 mapping 起始位置
    dwFileMapStart = (FILE_MAP_START / dwSysGran) * dwSysGran;


    dwMapViewSize = (FILE_MAP_START % dwSysGran) + BUFSIZE;        //mapping view 大小


    dwFileMapSize = FILE_MAP_START + BUFSIZE;                    // mapping 的大小

    iViewDelta = FILE_MAP_START - dwFileMapStart;                // 需要读取的数据的便宜


    hMapFile = CreateFileMapping ( hFile,                // 需要映射的文件句柄
                                   NULL,                // 使用默认安全选项
                                   PAGE_READWRITE,        // 可读,可写
                                   0,                    // mapping 对象的大小,高位
                                   dwFileMapSize,        // mapping 对象的大小,低位
                                   NULL);
    if (hMapFile == NULL) {
        printf ("CreateFileMapping error : %d\n", GetLastError());
        return (-2);
    }

    // 映射 view
    lpMapAddress = MapViewOfFile ( hMapFile,             // mapping 对象的句柄
                                   FILE_MAP_ALL_ACCESS,  // 可读,可写
                                   0,                     // 映射的文件偏移,高位
                                   dwFileMapStart,         // 映射的文件偏移,低位
                                   dwMapViewSize);         // 映射到 View 的文件大小


         _tprintf (TEXT("文件视图(map view)相对于文件的起始位置:0x%x\n"), dwFileMapStart);

    _tprintf (TEXT("文件视图(map view)的大小:0x%x\n"), dwMapViewSize);

    _tprintf (TEXT("文件映射对象的大小:0x%x\n"), dwFileMapSize);

    _tprintf (TEXT("从相对于文件视图(map view)的 0x%x 字节处读取数据为:"), iViewDelta);

    pData = (PCHAR)lpMapAddress + iViewDelta;    //设置指针

    iData = *(PINT)pData;    //读取一个数据

    _tprintf (TEXT("0x%.8x\n"), iData);



    CloseHandle (hMapFile);
    CloseHandle (hFile);

    return 0;
}

运行输出:
D:\WinAPI\MappingFile\Debug>MappingFile.exe d:\tmp.txt
文件大小:262140
文件视图(map view)相对于文件的起始位置:0x20000
文件视图(map view)的大小:0x8c04
文件映射对象的大小:0x28c04
从相对于文件视图(map view)的 0x8804 字节处读取数据为:0x0000a201
在最红一行的输出中,读取到的数据是 0x0000a201 ,该数据可通过用 UE 之类的文本编辑器打开 tmp.txt 来验证,如下图所示:





欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2