曲径通幽论坛

标题: CreateFileMapping() -- 创建或打开文件映射对象 [打印本页]

作者: beyes    时间: 2012-2-20 13:46
标题: CreateFileMapping() -- 创建或打开文件映射对象
CreateFileMapping() 原型如下:
[C++] 纯文本查看 复制代码
HANDLE WINAPI CreateFileMapping(
  __in      HANDLE hFile,
  __in_opt  LPSECURITY_ATTRIBUTES lpAttributes,
  __in      DWORD flProtect,
  __in      DWORD dwMaximumSizeHigh,
  __in      DWORD dwMaximumSizeLow,
  __in_opt  LPCTSTR lpName
);

该函数用来为一个指定文件创建或打开一个命名的或未命名的映射对象。

第 1 个参数 hFile 是由 CreateFile()创建的文件句柄。

第 2 个参数 lpAttributes 是指向 SECURITY_ATTRIBUTES 结构的指针。在一般情况下,使用默认属性即可,此时可将该参数设置为 NULL 。

第 3 个参数 flProtect 是内存保护属性。可以是下面几种值:

PAGE_EXECUTE_READ,PAGE_EXECUTE_READWRITE,PAGE_EXECUTE_WRITECOPY,PAGE_READONLY,PAGE_READWRITE,PAGE_WRITECOPY 。

第 4 个参数 dwMaximumSizeHigh 是映射大小的高 32 位。

第 5 个参数 dwMaximumSizeLow 是映射大小的低 32 位。

第 6 个参数 lpName 是映射对象名。如果该参数匹配了已经存在的映射对象,那么函数就会以第 3 个参数所指定的权限来访问该对象。如果该参数为 NULL,那么所创建的映射对象就没有名字。一般情况下,可设该参数为 NULL 。

创建文件映射对象使用该函数,但在函数执行后,并不说明已经将文件的视图映射到了进程的虚拟地址空间,后续还需要使用MapViewOfFile()   函数将文件视图进行映射,而该函数正是会用 CreateFileMapping() 所返回的对象句柄作为参数进行文件的映射。

文件映射机理可参考下图:


测试代码
[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 来验证,如下图所示:
[attach]223[/attach]




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