文件映射原理及实现
Posted 那时是什么时候
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件映射原理及实现相关的知识,希望对你有一定的参考价值。
文件内容关联进程虚拟地址空间。
文件视图是虚拟地址空间的一部分,进程可访问。
文件映射允许进程使用随机IO和顺序IO。
进程之间使用文件映射共享数据。
进程高效处理大数据文件,例如数据库,不需要映射整个文件到内存。
进程写和读文件视图使用指针,动态分配内存。
使用文件映射能够提供访问效率,因为文件存在磁盘,而文件视图存在内存。
进程可以操作文件视图使用VirtualProtect函数。
这张图可以解释了文件映射对象和文件视图的关系。
硬盘文件想要映射到进程内存,首先要获得文件映射对象,文件映射对象仅包含文件的一部分,由磁盘文件提供支持。
若系统交换出了文件映射对象页,任何对文件映射对象的改变都会写入到文件。如果系统换回时,会立马改变文件的内容。主要目的是文件映射对象修改后保持与本地文件的数据一致性。
文件视图仅包含文件映射对象的一部分。进程通过操作文件视图达到操作文件的目的。
进程可以创建多个文件视图从一个文件映射对象。文件视图存在于进程的虚拟内存空间中。
当进程需要其他数据时,当前文件视图不能提供,进程会卸载当前文件视图并创建一个新的文件视图。
多个进程使用同一个文件映像对象创建视图,数据是一致的。文件视图会包含本地文件完全相同的拷贝。
进程不能共享存储在远程计算机的文件。
创建文件映射对象:
调用CreateFile 打开文件,打开模式需要选择独占模式,防止其他进程能够写入到被映射的文件部分。
文件句柄需要一直保持打开,直到进程不再需要文件映射对象。
简单的方法是获取独占访问并且对CreateFile的参数fdwShareMode 指定为0。
创建的文件句柄会被CreateFileMapping调用用来创建文件映射对象。返回文件创建对象的句柄。
CreateFileMapping 返回的文件对象句柄会用来创建文件对象视图。
如果文件映射对象超过了文件大小,需要扩大文件,在CreateFileMapping返回之前。
dwMaximumSizeHigh 和dwMaximumSizeLow 两个CreateFileMapping函数参数允许指定字节的文件被映射。
不想要改变映射的文件对象,可以dwMaximumSizeHigh和dwMaximumSizeLow设置为0。
文件映射对象一旦被创建,大小是不能改变的。
创建文件视图:
文件分配粒度为64K。
如果想要view 1K,文件视图开始从135K开始。那么64K的倍数离135K最近是128K开始。
128K+8=136K因此偏移7K,所以文件视图开始为128K+偏移7K。
/*
This program demonstrates file mapping, especially how to align a
view with the system file allocation granularity.
*/
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define BUFFSIZE 1024 // size of the memory to examine at any one time
#define FILE_MAP_START 138240 // starting point within the file of
// the data to examine (135K)
/* The test file. The code below creates the file and populates it,
so there is no need to supply it in advance. */
TCHAR * lpcTheFile = TEXT("fmtest.txt"); // the file to be manipulated
int main(void)
HANDLE hMapFile; // handle for the file's memory-mapped region
HANDLE hFile; // the file handle
BOOL bFlag; // a result holder
DWORD dBytesWritten; // number of bytes written
DWORD dwFileSize; // temporary storage for file sizes
DWORD dwFileMapSize; // size of the file mapping
DWORD dwMapViewSize; // the size of the view
DWORD dwFileMapStart; // where to start the file map view
DWORD dwSysGran; // system allocation granularity
SYSTEM_INFO SysInfo; // system information; used to get granularity
LPVOID lpMapAddress; // pointer to the base address of the
// memory-mapped region
char * pData; // pointer to the data
int i; // loop counter
int iData; // on success contains the first int of data
int iViewDelta; // the offset into the view where the data
//shows up
// Create the test file. Open it "Create Always" to overwrite any
// existing file. The data is re-created below
hFile = CreateFile(lpcTheFile,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
_tprintf(TEXT("hFile is NULL\\n"));
_tprintf(TEXT("Target file is %s\\n"),
lpcTheFile);
return 4;
// Get the system allocation granularity.
GetSystemInfo(&SysInfo);
dwSysGran = SysInfo.dwAllocationGranularity;
// Now calculate a few variables. Calculate the file offsets as
// 64-bit values, and then get the low-order 32 bits for the
// function calls.
// To calculate where to start the file mapping, round down the
// offset of the data into the file to the nearest multiple of the
// system allocation granularity.
dwFileMapStart = (FILE_MAP_START / dwSysGran) * dwSysGran;
_tprintf (TEXT("The file map view starts at %ld bytes into the file.\\n"),
dwFileMapStart);
// Calculate the size of the file mapping view.
dwMapViewSize = (FILE_MAP_START % dwSysGran) + BUFFSIZE;
_tprintf (TEXT("The file map view is %ld bytes large.\\n"),
dwMapViewSize);
// How large will the file mapping object be?
dwFileMapSize = FILE_MAP_START + BUFFSIZE;
_tprintf (TEXT("The file mapping object is %ld bytes large.\\n"),
dwFileMapSize);
// The data of interest isn't at the beginning of the
// view, so determine how far into the view to set the pointer.
iViewDelta = FILE_MAP_START - dwFileMapStart;
_tprintf (TEXT("The data is %d bytes into the view.\\n"),
iViewDelta);
// Now write a file with data suitable for experimentation. This
// provides unique int (4-byte) offsets in the file for easy visual
// inspection. Note that this code does not check for storage
// medium overflow or other errors, which production code should
// do. Because an int is 4 bytes, the value at the pointer to the
// data should be one quarter of the desired offset into the file
for (i=0; i<(int)dwSysGran; i++)
WriteFile (hFile, &i, sizeof (i), &dBytesWritten, NULL);
// Verify that the correct file size was written.
dwFileSize = GetFileSize(hFile, NULL);
_tprintf(TEXT("hFile size: %10d\\n"), dwFileSize);
// Create a file mapping object for the file
// Note that it is a good idea to ensure the file size is not zero
hMapFile = CreateFileMapping( hFile, // current file handle
NULL, // default security
PAGE_READWRITE, // read/write permission
0, // size of mapping object, high
dwFileMapSize, // size of mapping object, low
NULL); // name of mapping object
if (hMapFile == NULL)
_tprintf(TEXT("hMapFile is NULL: last error: %d\\n"), GetLastError() );
return (2);
// Map the view and test the results.
lpMapAddress = MapViewOfFile(hMapFile, // handle to
// mapping object
FILE_MAP_ALL_ACCESS, // read/write
0, // high-order 32
// bits of file
// offset
dwFileMapStart, // low-order 32
// bits of file
// offset
dwMapViewSize); // number of bytes
// to map
if (lpMapAddress == NULL)
_tprintf(TEXT("lpMapAddress is NULL: last error: %d\\n"), GetLastError());
return 3;
// Calculate the pointer to the data.
pData = (char *) lpMapAddress + iViewDelta;
// Extract the data, an int. Cast the pointer pData from a "pointer
// to char" to a "pointer to int" to get the whole thing
iData = *(int *)pData;
_tprintf (TEXT("The value at the pointer is %d,\\nwhich %s one quarter of the desired file offset.\\n"),
iData,
iData*4 == FILE_MAP_START ? TEXT("is") : TEXT("is not"));
// Close the file mapping object and the open file
bFlag = UnmapViewOfFile(lpMapAddress);
bFlag = CloseHandle(hMapFile); // close the file mapping object
if(!bFlag)
_tprintf(TEXT("\\nError %ld occurred closing the mapping object!"),
GetLastError());
bFlag = CloseHandle(hFile); // close the file itself
if(!bFlag)
_tprintf(TEXT("\\nError %ld occurred closing the file!"),
GetLastError());
return 0;
以上是关于文件映射原理及实现的主要内容,如果未能解决你的问题,请参考以下文章