曲径通幽论坛

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

[文件与IO] FlushViewOfFile() -- 将视图中的数据写入到磁盘

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2012-2-20 23:26:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
FlushViewOfFile() 原型如下:
[C++] 纯文本查看 复制代码
BOOL WINAPI FlushViewOfFile(
  __in  LPCVOID lpBaseAddress,
  __in  SIZE_T dwNumberOfBytesToFlush
);

该函数将视图中的文件数据写入到磁盘。调用该函数后,对映射视图的内存操作会写回到磁盘上的文件中。

第 1 个参数 lpBaseAddress 是需要写入到文件的数据的起始位置。

第 2 个参数 dwNumberOfBytesToFlush 是写入的字节数,如果改值为 0 ,那么将整个视图都写回。

如果函数返回值是非零值那么表示执行成功,否则失败。

注意,即使不调用该函数,数据最终也会写回到磁盘,但调用该函数,一般情况下,数据会立刻写回到磁盘。

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

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

typedef struct {
    int i;
    int b;
}are;

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;            

    //创建一个文件
    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);

    _tprintf (TEXT("从视图起始的 32 个字节是:\n"));

    for (i = 1; i <= 32; i++) {
        printf ("0x%.2x ", *((unsigned char *)lpMapAddress + i - 1));
        if (i % 16 == 0)
            printf ("\n");
    }

    FillMemory(lpMapAddress, 32, (BYTE)0xff);

    //将数据写回到硬盘上
    FlushViewOfFile (lpMapAddress, dwMapViewSize);
    //FlushFileBuffers(hFile);

    CloseHandle (hMapFile);
    CloseHandle (hFile);

    return 0;
}

在将数据写回到硬盘前,先观察一下从文件偏移地址 0x20000 开始的 32 个字节数据,如下图所示:

执行程序后比较一下发现数据已经写入:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-6-19 03:27 , Processed in 0.084104 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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