曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5620|回复: 0
打印 上一主题 下一主题

[文件与IO] MapViewOfFile() -- 将文件视图映射到调用进程空间

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2012-2-20 15:16:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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 来验证,如下图所示:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-19 03:41 , Processed in 0.091559 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表