内存映射文件学习笔记
2008-01-28 02:02
417 查看
作为访问文件的一种方式,内存映射文件的确使用相当方便.只需在正常的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的一个特性吧,至少对程序员是方便的,不必判断是否是最后一次映射,然后再计算剩余大小.
特别是对于大文件的访问,不必太大,只要到几十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的一个特性吧,至少对程序员是方便的,不必判断是否是最后一次映射,然后再计算剩余大小.
相关文章推荐
- java_croe 学习笔记之新IO---java.nio 之内存映射文件
- 黑马程序员_O‘Reilly java nio学习笔记之通道_内存映射文件&&Channel-to-Channel 传输
- 内存映射文件 学习笔记
- VC下学习内存映射文件笔记
- windows笔记-内存映射文件
- Mybatis 源码学习笔记(八)mapper映射文件配置之select、resultMap
- 朱老师ARM裸机学习笔记(二):S5PV210的内存映射
- Java学习笔记(十三)——通过Netbeans开发环境生成oracle数据库中表的对应hibernate映射文件
- windows笔记-内存映射文件
- windows笔记-页文件支持的内存映射文件
- windows笔记-页文件支持的内存映射文件
- uClinux学习笔记之二 - 将新增应用程序编译进内存镜像文件
- mybatis学习笔记(十二) 映射配置文件详解
- linux内存学习笔记(三)——静态映射与DMA
- UNIX环境高级编程学习之第十五章进程间通信 - 两个进程通过映射普通文件实现共享内存通信
- [原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点,在hibernate 中 java类型 与sql类型之间的对应关系,Java 时间和日期类型的映射,Java 大对象类型 的 映射 (了解),映射组成关系
- 【知了堂学习笔记】——mybatis核心配置文件和映射配置文件
- Java NIO笔记(六):内存映射文件及文件通道到通道批量传输数据
- Hibernate学习之 -- 使用Middlegen-Hibernate-r5创建oracle10g的table的hibernate映射文件,Hibernate学习笔记三 ---持久化类和关系数据
- Nhibernate 2.0 学习笔记,关于hbm映射文件的重要性