内存映射文件学习笔记

     作为访问文件的一种方式,内存映射文件的确使用相当方便.只需在正常的CreateFile完成后通过CreateFileMapping映射到内存,之后就可以像访问内存那样的使用文件了.而且此时文件的缓存是由系统自动调节的,性能和安全性都要提高很多.

      特别是对于大文件的访问,不必太大,只要到几十K,记事本就吃不消了,也即普通的打开文件方式若不加以优化此时性能会很难接受.但采用内存映射文件做这点就小CASE了.下面是一个例子

      HANDLE hFile=CreateFile ("E://DATA.TXT",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
    printf ("failed to open file!/n");
    return ;
}
HANDLE hFileMapping=CreateFileMapping (hFile,NULL,PAGE_READWRITE,0,0,NULL);
DWORD dwFileSizeHigh;
__int64 qwFileSize=GetFileSize (hFile,&dwFileSizeHigh);
CloseHandle (hFile);
qwFileSize+=(((__int64)dwFileSizeHigh)<<32);
printf ("file length:%d/n",qwFileSize);
PBYTE pbBuf,pbTest;
__int64 qwFileOffSet=0;    //存储缓存中的指针偏移量
printf ("value of file:/n");
SYSTEM_INFO sinf;
GetSystemInfo (&sinf);
DWORD dwStep=sinf.dwAllocationGranularity;//得到系统的粒度大小,32机是65536
if (qwFileSize<dwStep)
    dwStep=(DWORD)qwFileSize;
while (qwFileSize>0)
{

//可对同一个文件作多个数据视图,且具有相关性
    pbBuf=(PBYTE)MapViewOfFile (hFileMapping,FILE_MAP_READ,(DWORD)(qwFileOffSet>>32),
     (DWORD)(qwFileOffSet&0XFFFFFFFF),dwStep);
    pbTest=(PBYTE)MapViewOfFile (hFileMapping,FILE_MAP_WRITE,(DWORD)(qwFileOffSet>>32),
     (DWORD)(qwFileOffSet&0XFFFFFFFF),3);
    pbTest[0]='a';
    printf ("%s",pbBuf);
    qwFileOffSet+=dwStep;
    qwFileSize-=dwStep;
    UnmapViewOfFile (pbBuf);
    UnmapViewOfFile (pbTest);
}

上面的程序运行会将文件每隔系统粒度大小修改字符为'a',开始时程序曾出现错误,这里要注意的是:

1.数据视图的权限继承于文件打开时的权限.假如文件打开时只有read权限,即使在创建视图也即CreateFileMapping时使用write权限,在试图修改时也会出错.比如语句pbTest[0]='a';就会出错.

2.同一个文件的多个视图系统自动维护其一致性,因为其对应的内存地址是唯一的.所以修改了pbTest[0],pbBuf[0]的内容也会相应变化.

3.通过GetSystemInfo可以得到系统的内存粒度大小.但假如文件本身小于此粒度,访问则会出错.但事实上若文件不是64KB的整数倍,最后一次调用MapViewOfFile时的映射也会访问文件越界但却没有问题,这一点可以算是MapViewOfFile的一个特性吧,至少对程序员是方便的,不必判断是否是最后一次映射,然后再计算剩余大小.

 

posted on 2008-01-28 02:02  magicyang87  阅读(104)  评论(0)    收藏  举报

导航