内存映射文件
来源:互联网 发布:淘宝客服的工资有多少 编辑:程序博客网 时间:2024/05/22 02:02
本文内容全部引子windows核心编程。只因今天详细的看了一下,特做了摘抄而已!
内存映射文件最好用于只读独占的方式打开,因为如果采用可写的方式的话,不能保证一个进程的修改立
即在另一个进程生效。以独占方式打开就禁止了其他进程的访问。下面详细介绍一下使用文件映射的步骤
和方法:
步骤1:创建或打开文件内核对象
HANDLE CreateFile(
PCSTR pszFileName,
DWORD dwDesiredAccess, //GENERIC_READ 只读
DWORD dwShareMode, //0 独占
PSECURITY_ATTRIBUTES psa,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
步骤2:创建一个文件映射内核对象
调用C r e a t e F i l e函数,就可以将文件映像的物理存储器的位置告诉操作系统。你传递的路径名
用于指明支持文件映像的物理存储器在磁盘(或网络或光盘)上的确切位置。这时,必须告诉系统,文件
映射对象需要多少物理存储器。若要进行这项操作,可以调用C r e a t e F i l e M a p p i n g函数
:
HANDLE CreateFileMapping(
HANDLE hFile,
PSECURITY_ATTRIBUTES psa,
DWORD fdwProtect, //PAGE_READONLY
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
PCTSTR pszName);
这里需要说明一点的是fdwProtect中的PAGE_WRITECOPY当文件映射对象被映射时,可以读取和写入文件的
数据。如果写入数据,会导致页面的私有拷贝得以创建。必须已经将G E N E R I C _ R E A D或G E N E
R I C _ W R I T E传递给C r e a t e F i l e
步骤3:将文件数据映射到进程的地址空间
当创建了一个文件映射对象后,仍然必须让系统为文件的数据保留一个地址空间区域,并将文件的数据作
为映射到该区域的物理存储器进行提交。可以通过调用M a p Vi e w O f F i l e函数来进行这项操作:
PVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess, //FILE_MAP_READ
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap);
如果在调用M a p Vi e w O f F i l e函数时设定了F I L E _ M A P _ C O P Y标志,系统就会从系统
的页文件中提交物理存储器。提交的地址空间数量由d w N u m b e r O f B y t e s To M a p参数决定
。只要你不进行其他操作,只是从文件的映像视图中读取数据,那么系统将决不会使用页文件中的这些提
交的页面。但是,如果进程中的任何线程将数据写入文件的映像视图中的任何内存地址,那么系统将从页
文件中抓取已提交页面中的一个页面,将原始数据页面拷贝到该页交换文件中,然后将该拷贝的页面映射
到你的进程的地址空间。从这时起,你的进程中的线程就要访问数据的本地拷贝,不能读取或修改原始数
据。当系统制作原始页面的拷贝时,系统将把页面的保护属性从PA G E _ W R I T E C O P Y改为PA G E
_ R E A D W R I T E。
这时就可以通过返回的视图文件指针对文件进行操作了。
步骤4:从进程的地址空间中撤消文件数据的映像
BOOL UnmapViewOfFile(PVOID pvBaseAddress) //该值必须与调用M a p Vi e w O f F i l e函数返回的
值相同
步骤5和步骤6:关闭文件映射对象和文件对象
CloseHandle(hFileMapping);
CloseHandle(hFile);
详细使用方法举例,这个例子实在是太经典了。学习学习
__int64 Count0s(void)
{
//Views must always start on a multiple
//of the allocation granularity
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
//Open the data file.
HANDLE hFile = CreateFile("C://HugeFile.Big", GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
//Create the file-mapping object.
HANDLE hFileMapping = CreateFileMapping(hFile, NULL,
PAGE_READONLY, 0, 0, NULL);
DWORD dwFileSizeHigh;
__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
qwFileSize += (((__int64) dwFileSizeHigh) << 32);
//We no longer need access to the file object's handle.
CloseHandle(hFile);
__int64 qwFileOffset = 0, qwNumOf0s = 0;
while (qwFileSize > 0)
{
// Determine the number of bytes to be mapped in this view
DWORD dwBytesInBlock = sinf.dwAllocationGranularity;
if(qwFileSize < sinf.dwAllocationGranularity)
dwBytesInBlock =(DWORD) qwFileSize;
PBYTE pbFile = (PBYTE) MapViewOfFile(hFileMapping, FILE_MAP_READ,
(DWORD)(qwFileOffset >> 32), // Starting byte
(DWORD)(qwFileOffset & 0xFFFFFFFF), // in file
dwBytesInBlock); // # of bytes to map
// Count the number of Js in this block.
for(DWORD dwByte = 0; dwByte < dwBytesInBlock; dwByte++)
{
if(pbFile[dwByte] == 0)
qwNumOf0s++;
}
// Unmap the view; we don't want multiple views
// in our address space.
UnmapViewOfFile(pbFile);
// Skip to the next set of bytes in the file.
qwFileOffset += dwBytesInBlock;
qwFileSize -= dwBytesInBlock;
}
CloseHandle(hFileMapping);
return(qwNumOf0s);
}
这个算法用于映射64 KB(分配粒度的大小)或更小的视图。另外,要记住, M a p Vi e wO f F i l e
函数要求文件的位移是分配粒度大小的倍数。当每个视图被映射到地址空间时,对0的扫描不断进行。当
每个64 KB的文件块已经映射和扫描完毕时,就要通过关闭文件映射对象来对每个文件块进行整理。
- 内存映射:内存映射文件
- 内存映射:内存映射文件
- 内存映射文件
- 内存映射文件 续
- 内存映射文件 尾
- 内存映射文件
- 使用内存映射文件
- 内存映射文件
- 内存映射文件
- 内存映射文件技术
- 内存映射文件
- 内存映射文件
- 内存映射文件
- 内存映射文件
- 使用内存映射文件
- 内存映射文件技术
- 内存映射文件
- 内存映射文件
- Git和Github
- 窗口创建和关系
- java函数参数默认值
- Extjs学习总结之28viewport
- 错误分析
- 内存映射文件
- uva 10161 Ant on a Chessboard
- Extjs学习总结之感想
- 正则表达式验证输入框是否为数字
- iCabMobile更新后,Installous的Downloads不能用的解决方法
- 自定义ListView FastScroller滑块图片
- Linux下3G的应用
- 插件系统结构浅析
- 服务程序与桌面的交互